2

In my thunk, I have two dispatches in an array called dispatches which modify the Redux store. Only after both of them have completed (i.e., modified the Redux store), I want to dispatch finalDispatchCall. I tried putting them both in a Promise and called then, but I still see the finalDispatchCall being made before the secondDispatchCall has updated the Redux store.

const dispatches = [];
dispatches.push(dispatch(firstDispatchCall());
dispatches.push(dispatch(secondDispatchCall());
Promise.all([...dispatches]).then(() => {
 dispatch(finalDispatchCall());
})
.catch(error => {
 logger.error(
  `Print out error - ${error}`
 );
});

Is there a way to make sure a dispatch has completed before calling another dispatch?

EDIT (more details):

The firstDispatchCall is making an API call (returning fetch) and dispatching an action in the then statement to update the redux store. The secondDispatchCall is also making an API call (returning fetch) and dispatching two other actions in their then statements which each make their own API calls and dispatch actions to update the redux store.

I want to wait until all of this is complete before making that finalDispatchCall.

covfefe
  • 2,485
  • 8
  • 47
  • 77
  • Seems like your `firstDispatchCall` and `secondDispatchCall` actions are immediately resolving (returning a resolved value) before they are finished doing work. You'll need to share what these actions are actually doing so we can help your code wait for them. I suspect you are mixing `async/await` with a Promise chain and not actually awaiting anything in the actions. – Drew Reese Aug 05 '21 at 22:59
  • @DrewReese The `firstDispatchCall` is making an API call (returning `fetch`) and dispatching an action in the `then` statement to update the redux store. The `secondDispatchCall` is also making an API call (returning `fetch`) and dispatching two other actions in their `then` statements which each make their own API calls and dispatch actions to update the redux store. I want to wait until all of this is complete before making that `finalDispatchCall`. – covfefe Aug 05 '21 at 23:43

2 Answers2

2

As long as firstDispatchCall() and secondDispatchCall() are sync, then redux guarantees that they'll arrive synchronously, in sequence, and that subsequent calls to dispatch() will act upon the updated state. But, if you want to be absolutely certain, you can use store.subscribe(), to kind of procedurally await all the changes you're expecting, and read the store on each change to confirm they're all there. This will actually be essential if first and second DispatchCall are async.

But, the question is whether you really need to know, from that specific thunk, when all the dispatches have landed. Redux is an event bus, and as such offers many ways to skin the async cat. It might help to understand more about the problem you're trying to solve by waiting for these dispatches in order to dispatch the last one. It may be that you don't really need to do that...

I recommend reading the Redux team's take on this exact question: "Should I dispatch multiple actions in a row from one action creator?". Especially note there:

"In general, ask if these actions are related but independent, or should actually be represented as one action."

Newcomers to Redux often use multiple actions for what could be a single action, because they forget that multiple reducers can all listen to the same action.

XML
  • 19,206
  • 9
  • 64
  • 65
  • 1
    Well, with regards to conventional redux and reducers, yes, AFAIK there is guaranteed order... they are processed in the order they are dispatched in since only a single action is processed at-a-time. You are correct though when it comes to thunks and the asynchronous middleware, whatever the asynchronous logic is doing can resolve in any order. – Drew Reese Aug 05 '21 at 22:57
  • Yeah, you're right, thanks. I think I remember that way back in the dark early ages of Redux, gaearon shocked us by saying it didn't provide explicit guarantees, and that people should plan accordingly, but that appears not to be true any more. (If it ever was). – XML Aug 06 '21 at 16:47
  • All hail Gaearon. Yeah, I could agree with the statement that Redux doesn't provide explicit guarantees, but maybe it doesn't need to. I think the sequential processing of dispatched actions in a single threaded, synchronous javascript world is enough of a guarantee to rely on. (*Hopefully I'm not just making baseless assumptions*) – Drew Reese Aug 06 '21 at 16:59
  • 1
    He says: "Actions are dispatched synchronously so Redux guarantees the store has received the next state before accepting the next action." --https://github.com/reduxjs/redux/issues/1199 – XML Aug 06 '21 at 18:58
0
dispatch(
          deleteEventDeteailsThunk({
            id: deletedIdEvents[0].id
          })
        )
          .unwrap()
          .then((resp) => {
            // handle result here
            res(deletedId);
          })
          .catch((err) => {
            // handle error here
            res({});
          });

for reference :Redux toolkit thunk wait for state change