Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle two consecutive and dependent Async calls in Redux?

Tags:

redux

I am getting a list of posts asynchronously by calling an action fetchPosts from a Component on componentDidMount. I would like, once that request is received and handled by the relevant reducer (which updates the state), to call another action fetchPostsMetaData, with an array of the just-received posts' ids.

I am using redux-thunk middleware, and making my ajax requests using jQuery.ajax

What is the best way to go about this? I tried googling but couldn't find a relevant example / answer.

like image 520
lior Avatar asked Oct 26 '15 10:10

lior


People also ask

How do you handle asynchronous calls in Redux?

Redux Async Data Flow​ Just like with a normal action, we first need to handle a user event in the application, such as a click on a button. Then, we call dispatch() , and pass in something, whether it be a plain action object, a function, or some other value that a middleware can look for.

Which middleware did we use to handle the asynchronous operations in Redux application?

Writing middleware for Redux is a powerful tool; Redux Thunk is one of the most widely-used middleware for async actions. Thunk is also a default async middleware for Redux Toolkit and RTK Query. If you want a simple API integration for your Redux apps, RTK Query is a highly recommended option.

What are typical middleware choices for handling asynchronous calls in Redux?

There are two very popular middleware libraries that allow for side effects and asynchronous actions: Redux Thunk and Redux Saga. In this post, you will explore Redux Thunk. Thunk is a programming concept where a function is used to delay the evaluation/calculation of an operation.

Is Redux dispatch asynchronous?

Redux can dispatch asynchronous actions so that we don't always have to change states synchronously. To do this, we use the Redux-Thunk middleware. We can apply middlewares by using Redux's applyMiddleware function. With that, we can pass in functions that call dispatch instead of plain objects.


1 Answers

Using 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
}

This is a pretty standard use-case for redux-thunk. The above example is catered towards the way you're asking the question, but you could accomplish this in a single action creator that looks the the redux-thunk example provided here: http://redux.js.org/docs/advanced/AsyncActions.html

Whats different is that in my example, I'm dispatching a thunk inside of a thunk, rather than doing the second task directly inside of the first thunk. So its equivalent to this:

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 });
      })
  }
}

You won't run into any race conditions because when you dispatch an action like { type: RECEIVE_POSTS, payload: res }, it is synchronous and the reducer updates before you dispatch the following async action.

like image 115
Nathan Hagen Avatar answered Sep 28 '22 03:09

Nathan Hagen