0

Background

I am having react application which uses redux and redux-thunk.

Trying to understand how to orchestrate async calls. How to dispatch actions only if previously dispatched action (API call) was successul.

Use Case

I have EmployeesComponent. That component has two dummy presentational components

  • EmployeesList which basically lists employees.
  • AddEmployeeForm which is a modal for adding new employees.

When rendering the EmployeesComponent, within the useEffect hook, I dispatch an action to load employees. So far, so good.

When I user enters data in the AddEmployeeForm and submits the form, I want to achieve the load all employees again if the API call was successful.

I have issues understanding how to know if I am okay to dispatch the action to load all employees. Here is how my handler for submit looks like.

   const handleSubmit = async (e) => {
        e.preventDefault();
    
        console.log("Handle submit add new employee..");
    
        const employeeData = inputs;
        // Validate data from the AddEmployeeForm
        // in case of validation errors, abort



       dispatch(addEmployee(employeeData)); // calls API to save the data

       // How to await the result of the dispatched action (addEmployee) before continuing? 

       // If addEmployee was not successful abort
       // The error data from the API call is saved in the redux store, 
       // so the UI gets notified and can display it properly

        // If addEmployee was successful, I want to
        clearForm(); // local state from the component
        handleCloseForm(); // local state from the component

        dispatch(loadEmployees());
      };

Challenges

The current approach in handleSubmit smells to me. The business logic is kinda placed in the UI and the benefits of clearly separating the UI and business logic are lost. I have difficulties to figure out what is the approach to go and how to handle this use cases.

Another use case example:

  • dispatch login user
  • if login was successful, you get token from the backend
  • if login was successful, dispatch an action to load user data based on retrieved token
Hola
  • 329
  • 3
  • 18

1 Answers1

3

In Redux, async logic is normally written in the form of "thunk" functions. That lets you extract logic that needs to interact with the store outside of your React components, especially async logic that needs to do things like fetching data and dispatching the results.

You can also return a promise from a thunk and await that promise in the component after dispatching.

markerikson
  • 63,178
  • 10
  • 141
  • 157
  • Thank you @markerikson Can you recommend a pattern or a tutorial of a a good approach how the UI should subscribe a result from an async call? Like do I declare in the state all possible events? Like "employeeCreatedStatus" and then have a reducer which sets the status for that event? Or based on the example above, how should UI know that its okay to perform clearForm() and handleCloseForm() ? EDIT: Did not read properly for async thunk and awaiting the promise. Going to dig into it. By any chance, can you recommend video as well? – Hola Mar 22 '21 at 02:42
  • Please read through the ["Redux Essentials"](https://redux.js.org/tutorials/essentials/part-1-overview-concepts) and ["Redux Fundamentals"](https://redux.js.org/tutorials/fundamentals/part-1-overview) tutorials in the Redux core docs, which show our current recommended patterns for using Redux and working with async logic. – markerikson Mar 22 '21 at 15:58