Search code examples
javascriptreduxredux-thunk

When does Redux resolve a dispatch if my action creator return promise?


This post, Dan write a snippet to demonstrate async action.

I'm wondering how does Redux know my store is completely updated ?

Is there a chance that fetchedUser has not updated yet during executing dispatch(getUser(userId)).then ?

What will happen if I write setTimeout(()=>{ dispatch({ type: 'GET_USER_SUCCESS', id, response }) }, 5000) in fetchUser.then ?

export function getUser(id) {
  return dispatch => {
    dispatch({ type: 'GET_USER_REQUEST', id })

    // Perform the actual API call
    return fetchUser().then(
      response => {
        // Reducers may handle this to show the data and reset isFetching
        dispatch({ type: 'GET_USER_SUCCESS', id,  response })
      },
      error => { ... }
    )
  }
}



export function getUserAndTheirFirstPost(userId) {
  return (dispatch, getState) => {
    return dispatch(getUser(userId)).then(() => {
      // Assuming this is where the fetched user got stored
      const fetchedUser = getState().usersById[userId]

      // Assuming it has a "postIDs" field:

      const firstPostID = fetchedUser.postIDs[0]

      return dispatch(getPost(firstPostID))
    })
  } 
}

Kindly guide me for this.

Thank you


Solution

  • Redux is a library that works in a reactive way, so it waits for actions to be dispatched to spread the state changes to all the connected functions.

    If you set a 5 seconds timeout to dispatch an action, for Redux it's the same as if you wait 5 seconds in real life and then call dispatch(). It will just respond to that action by updating all the connected functions.

    Your question is more about promises.

    Is there a chance that fetchedUser has not updated yet during executing dispatch(getUser(userId)).then ?

    No, because you're using .then after the getUser action, and that is making sure that the fetchUser promise was already resolved. What could happen is that the user was not found or something like that, but in that block you can make sure that the fetchUser call is already completed.

    The flow would go like this:

    1. Call getUser(userId)
    2. Dispatch GET_USER_REQUEST
    3. Call fetchUser()
    4. Wait until fetchUser is completed.
    5. Dispatch GET_USER_SUCCESS
    6. Run fetchedUser = getState().usersById[userId]
    7. And so on..

    What will happen if I write setTimeout(()=>{ dispatch({ type: 'GET_USER_SUCCESS', id, response }) }, 5000) in fetchUser.then

    In this case, it could run the fetchedUser assignment line without the state being updated, since I assume what sets the user is the GET_USER_SUCCESS action, right? So if the request takes less than 5 seconds to complete, it would run the assignment before updating the state with the user data.