Search code examples
javascriptreactjsreduxredux-thunk

Executing async actions in order with Redux and React


In my React/Redux application I have custom group objects. I want to have a page which displays a summary list of all groups alongside a detailed view of the currently selected group (which defaults to the first group in the list). I need to request a list of groups (/groups) from my rest api, get the id of the first group (from the store?) and set that to be the selected group and then make a get request to return a list of members of the selected group (/groups/${id}/members)

I'm very new to React/Redux and I'm not sure how to go about coding this. Should I write this as 3 separate actions and can I make a react component call these actions using the results from the previous action? Or should I place the logic for this in a combined action handler using thunk middleware? How would I write such an action handler in that case?


Solution

  • It would probably be best to write 3 actions, then chain them together using thunk. Also, any requests are async, so they'll need to use thunk or some other async method anyway. So the requests to /groups and /groups/${id}/members will be thunks looking something like this (arrow functions only for brevity):

    export const requestGroups = () => (
      (dispatch) => {
        // Maybe dispatch an action here that says groups are loading,
        // for showing a loading icon or something
        return fetch('/groups').then((response) => (
          dispatch(updateGroups(response))
          // Or just dispatch({ type: 'UPDATE_GROUPS', groups: response })
        )
      }
    )

    Where updateGroups is an action that sends the response data to the reducers to put it into state. And make sure these thunks return promises so you can chain them together later. You'll probably also want to do some error handling here.

    Then once you have those three actions, you can make a thunk that combines them all:

    export const initializeGroups = () => (
      (dispatch, getState) => (
        dispatch(loadGroups()).then(() => {
          const { groups } = getState(); // Or wherever the list is
          setSelectedGroup(groups[0]);
          return getGroupData(groups[0]);
        }).then(() => {
          // Dispatch an action saying everything is done, or do any other stuff here.
        }).catch((error) => {
          // Do any error handling
        });
      )
     )