简体   繁体   中英

Redux: Dispatch actions in sequence

I'm creating a Reddit client on Redux and I have 2 store dispatches firing in the app:

// App()
const dispatch = useDispatch();

useEffect(() => {
    const stateMatch = window.location.href.match(/state=([^&]*)/);
    const codeMatch = window.location.href.match(/code=([^&]*)/);

    if ((stateMatch && codeMatch) || localStorage.getItem("access_token")) {
        dispatch(fetchUser());
        dispatch(fetchSubs());
    }
});

...

However, I want fetchUser() to run and finish before fetchSubs() can begin, as the former currently seems to ruin API calls for the latter while it's running. How can I solve this?

Since you are using createAsyncThunk you can do something like this:

  dispatch(fetchUser())
  .unwrap()
  .then((user) => {
    // do anything you want with user, or don't, also dispatch actions
    dispatch(fetchSubs());
  })
  .catch((e) => {
    // error in case of rejection inside createAsyncThunk second argument
    console.log(e);
  });

Explanation

Let's say const thunk = fetchUser() so basically dispatch(fetchUser()) is the same as dispatch(thunk) .

Redux's dispatch function returns whatever its argument (the action) returns.

So in this case, dispatch(thunk) returns whatever thunk returns.

thunk , based on how createAsyncThunk works, returns a promise that either resolves to fulfilled action, or the rejected action. (those actions that you receive in extra reducers).

This is how you can access those actions:

dispatch(thunk).then(fullfilledAction=>...).catch(rejectedAction=>...`

RTK library also provides a method called unwrap . Instead of those action objects I explained above, it lets you use the returned value from the 2nd argument of createAsyncThunk .

export const fetchUser = createAsyncThunk("user/fetchUser", async () => {
const user = await Reddit.getUser().then(val => {
    return val;
});

return user; // unwrap lets you use this instead of action objects.
})

Try this with pure react and redux hooks

...

const state = useStore(yourStore) //use your method to read state 
const dispatch = useDispatch();
const checkValue = () => {
   const stateMatch = window.location.href.match(/state=([^&]*)/);
    const codeMatch = window.location.href.match(/code=([^&]*)/);

    if ((stateMatch && codeMatch) || localStorage.getItem("access_token")) {
        return true;
    }
    return false;
}

useEffect(() => {
    if(checkValue())
        dispatch(fetchUser());
    }
}, []);

useEffect(() => {
    if(checkValue() && state.authState)
        dispatch(fetchSubs());
    }
}, [state.authState]);


...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM