1

I have two async thunks created by createAsyncThunk() function of redux-toolkit.

E.g.

const getOrder = createAsyncThunk('a/getOrder', async (_, thunkAPI) => {
  // `userId` from API.getUser()
  // I tried to get the `userId` from redux store, but got `undefined`.
  const user = thunkAPI.getState().user;
  const userId = user.userId;

  const response = await APIs.getOrder(userId);
  return response.result;
});

const getUser = createAsyncThunk('a/getUser', async () => {
  const response = await APIs.getUser();
  return response.result;
});

In component, I dispatched these two async thunks concurrently.

useEffect(() => {
  dispatch(getUser());
  dispatch(getOrder());
}, []);

getOrder thunk depend on the result of getUser() thunk. What's the correct way to get the userId parameter? Can I get the userId from the redux store user slice state?

Lin Du
  • 88,126
  • 95
  • 281
  • 483

2 Answers2

3

Can I get the userId from the redux store user slice state?

You can access the state in the thunk, but you can't get the userId if it doesn't exist yet.

It doesn't make sense to dispatch the two thunks concurrently when the call to APIs.getUser() must be completed before the call to APIs.getOrder(userId) can begin.


I recommend that getOrder takes the userId as an argument. You can get the userId from await-ing the resolution of the first dispatch.

import { isFulfilled } from "@reduxjs/toolkit";
useEffect(() => {
  const load = async () => {
    // is either a fulfilled or rejected action
    const action = await dispatch(getUser());
    if (isFulfilled(action)) {
      dispatch(getOrder(action.payload.userId));
    }
  };
  load();
}, [dispatch]);

Alternatively, you can dispatch the second action in a separate useEffect that depends on a userId variable selected from the state.

// is initially undefined, but then becomes an id
const userId = useSelector(state => state.user?.userId);

const dispatch = useDispatch();

// call getUser on mount
useEffect(() => {
  dispatch(getUser());
}, [dispatch]);

// call getOrder after you already have a userId
useEffect(() => {
  if (userId) {
    dispatch(getOrder(userId));
  }
}, [dispatch, userId]);
Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
0

In this case I would create a third thunk which can handle the async results, some kind of wrapper/helper thunk. The order and user getter thunks should be as minimal as possible. In that third thunk you can implement any complex logic based on the responses and any other stuff you would like to use and wait until you get back the user then call the order api endpoint with the desired params.

knightburton
  • 1,114
  • 9
  • 22