Правильный способ получения исходных данных в контейнере React Boilerplate - PullRequest
1 голос
/ 11 октября 2019

Я новичок в React Boilerplate и использую контейнеры и саги для получения начальных данных страницы. Я столкнулся с двумя проблемами при реализации этого.

UsersPage\index.js

// imported all sagas, etc

export function UsersPage({
  dispatch,
  usersPage,
  onGetUsers,
  onChangeSearch,
  onSetActive,
}) {

  useInjectReducer({ key: 'usersPage', reducer });
  useInjectSaga({ key: 'usersPage', saga });

  onGetUsers();

  return (...);
}

UsersPage.propTypes = {
  dispatch: PropTypes.func.isRequired,
  usersPage: PropTypes.object,
  onGetUsers: PropTypes.func,
  onChangeSearch: PropTypes.func,
  onSetActive: PropTypes.func,
};

const mapStateToProps = createStructuredSelector({
  usersPage: makeSelectUsersPage(),
});

function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    onGetUsers: () => dispatch(getUsers()),
    onChangeSearch: evt => dispatch(changeSearch(evt.target.value)),
    onSetActive: active => dispatch(setActive(active)),
  };
}

const withConnect = connect(
  mapStateToProps,
  mapDispatchToProps,
);

export default compose(withConnect)(UsersPage);

UsersPage\actions.js

...
export function getUsers() {
  console.log('action getUsers');
  return {
    type: constants.GET_USERS,
  };
}
...

UsersPage\saga.js

export function* getUsers() {
  console.log('saga getUsers');
  try {
    const response = yield call(api.users.getAll);
    yield put(
      getUsersSuccess({
        users: response.data.data,
      }),
    );
  } catch (err) {
    const error = err.response.data.message;
    yield put(getUsersFail(error));
  }
}

export default function* usersPageSaga() {
  yield takeLatest(constants.GET_USERS, getUsers);
}

Когда я впервые загрузил страницу, журнал консоли показывает следующее:

action getUsers
saga watcher

Однако, когда я перешел на другую страницу и затем перешел на эту страницу:

action getUsers
saga worker getUsers

ПРОБЛЕМА 1

Кажется, что при первой загрузке средство отслеживания саги вызывается позже, чем действие (getUsers). И, таким образом, он терпит неудачу при первой загрузке, но при последующей загрузке рабочий саги вызывается просто отлично. Как я могу убедиться, что saga watcher вызывается первым перед действием?

ПРОБЛЕМА 2

Поскольку действие (getUsers) находится внутри рендера, его вызывают каждый раз, когдаесть обновление. Поэтому, когда getUsers возвращают и применяют новые данные в редуктор, рендеринг вызывается снова и снова вызывается действие (getUsers), вызывая бесконечный цикл. Что мы должны сделать или как правильно загрузить исходные данные в контейнер?

1 Ответ

1 голос
/ 11 октября 2019

Чтобы устранить первую проблему, попробуйте использовать takeEvery вместо takeLatest:

export default function* usersPageSaga() {
  yield takeEvery(constants.GET_USERS, getUsers);
}

Что касается второй проблемы, вы можете загрузить исходные данные с помощью useEffect hook:

useEffect(()=> {
  // load the data
}, [])
...