Как обрабатывать два последовательных и зависимых асинхронных вызова в Redux?

Я получаю список сообщений асинхронно, вызывая действие fetchPosts из Компонента на componentDidMount. Я хотел бы, чтобы этот запрос был получен и обработан соответствующим редуктором (который обновляет состояние), чтобы вызвать другое действие fetchPostsMetaData, с массивом идентификаторов только что полученных сообщений.

Я использую redux-thunk промежуточное программное обеспечение и делаю свои запросы ajax с помощью jQuery.ajax

Каков наилучший способ сделать это? Я попробовал поиск по Google, но не смог найти соответствующий пример/ответ.

Ответы

Ответ 1

Использование redux-thunk:

class PostIndex extends React.Component {
  componentDidMount() {
    const { dispatch } = this.props;
    dispatch(getPosts());
  }
  ...
}

function fetchPosts() {
  return dispatch => {
    fetchPostsAjax()
      .then(res => {
        dispatch({ type: 'RECEIVE_POSTS', payload: res });
        dispatch(fetchPostMeta(res));
      })
  }
}

function fetchPostMeta(posts) {
  return dispatch => {
    fetchPostMetaAjax(posts)
      .then(res => dispatch({ type: 'RECEIVE_POST_META', payload: res }));
    }
  }
}

function fetchPostAjax() {
   // return a promise, whether from jQuery.ajax or fetch
}

function fetchPostMetaAjax() {
  // return a promise
}

Это довольно стандартный вариант использования для redux-thunk. Вышеприведенный пример удовлетворен тем, как вы задаете этот вопрос, но вы можете сделать это в одном создателе действия, который выглядит здесь: http://redux.js.org/docs/advanced/AsyncActions.html

Разница в том, что в моем примере я отправляю thunk внутри thunk, вместо того, чтобы выполнять вторую задачу непосредственно внутри первого thunk. Таким образом, это эквивалентно этому:

function fetchPosts() {
  return dispatch => {
    fetchPostsAsync()
      .then(res => { // res is posts
        dispatch({ type: 'RECEIVE_POSTS', payload: res });
        return fetchPostMetaAsync(res);
      })
      .then(res => { // res  is metadata
        dispatch({ type: 'RECEIVE_POST_META', payload: res });
      })
  }
}

Вы не столкнетесь с какими-либо условиями гонки, потому что, когда вы отправляете какое-либо действие, например { type: RECEIVE_POSTS, payload: res }, оно синхронно и обновления редуктора перед отправкой следующего действия async.