-1

In my React Redux project, I am writing a thunk, and want it to dispatch only if the previous update if any has been completed. I'm aware that thunks are methods that help us delay dispatching actions to the reducer, and they can also be asynchronous. Here is what my thunk looks like right now:

myThunkMethod = () => async (dispatch, getState) =>{
    dispatch(...my action...);
}

but I how can make dispatch be called only after the previous call / state update is complete

Divyansh Goenka
  • 997
  • 2
  • 12
  • 35

2 Answers2

0

You can combine and wait for thunks to complete as long as your thunk returns a promise: (dispatch,getState)=>Promise.

const thunkA = (arg) => (dispatch, getState) => {
  //do stuff and RETURN PROMISE
  return Promise;
};
const thunkB = (arg) => (dispatch, getState) => {
  //do stuff and RETURN PROMISE
  return Promise;
};
//combined thunk
const combinedThunk = (arg) => (dispatch, getState) =>
  tunkA(arg)(dispatch, getState).then(() =>
    thunkB(arg)(dispatch, getState)
  );
//from component
const Component = () => {
  const dispatch = React.useDispatch();
  React.useEffect(() => {
    dispatch(thunkA("some arg")).then(() =>
      dispatch(thunkB("someArg"))
    );
  }, [dispatch]);
};

Here is how you can do a recursive thunk:

const recursiveThunk = (times) => (dispatch, getState) => {
  if (times === 0) {
    return;
  }
  dispatch(started());
  somePromise().then(
    (result) => {
      dispatch(success());
      return recursiveThunk(times - 1)(dispatch, getState);
    },
    (reject) => dispatch(failed())
  );
};

It is unclear what you want in your question and your comment but if you want to call thunkA each time with an item from an array as parameter then you can do this:

const combinedThunk = (args) => (dispatch, getState) => {
  if (args.length === 0) {
    return;
  }
  return tunkA(args[0])(dispatch, getState).then(
    () => combinedThunk(args.slice(1))(dispatch, getState),
    (reject) => dispatch(failed(reject))
  );
};
//call thunkA with 1, then 2 and then 3
dispatch(combinedThunk([1, 2, 3]));
HMR
  • 37,593
  • 24
  • 91
  • 160
  • thanks for your effort, but instead of thunk A, B.. and something finite, I meant something like: A-> A-> A->.....->A where is A is the same thunk, but the dispatch happens only after the previous call is complete – Divyansh Goenka Dec 28 '20 at 09:39
  • @DivyanshGoenka So you want a recursive thunk, I added it to the answer. – HMR Dec 28 '20 at 10:27
0

Here is what you need to do:


const firstThunk = () => (dispatch, getState) => {
  // do or dispatch something here
  return Promise.resoleved("first thunk resolved");
}

const secondThunk = () => (dispatch, getState) => {
  // do or dispatch something here
  return Promise.resolved("second thunk resolved")
}

const thirdThunk = () => (dispatch, getState) => {
  // I want to first dispatch the first thunk
  dispatch(firstThunk()).then(result => {
    // first thunk successfully dispatched now it's time for secondThunk
    dispatch(secondThunk()).then(res => {
      // here both firstThunk and secondThunk dispatched successfully
    })
  }) 
}
Taghi Khavari
  • 6,272
  • 3
  • 15
  • 32
  • thanks for your effort, but instead of thunk A, B.. and something finite, I meant something like: A-> A-> A->.....->A where is A is the same thunk, but the dispatch happens only after the previous call is complete – Divyansh Goenka Dec 28 '20 at 09:40