Search code examples
javascriptreactjsredux

Async/Await not executing as expected


I have the below method where I am updating store and after store updating, I am performing certain activities based on store values -

useEffect(()=>{

const asyncUpdateStore=async()=>{
  
  await updateStore();
  getDetails(storeValues)    //this is api call made based on updated store values above
   .then(()=>{...})

}
asyncUpdateStore();

},[applyChange]);

Upon execution of this code , I find that getDetails which is internally a axios call is not waiting for store values to be get updated within updateStore() method. When useEffect is getting called second time , I find store is updated.

I want to wait execution of getDetails , till updateStore method finishes its execution.

I have also tried with -

 useEffect(()=>{    
    const asyncUpdateStore=async()=>{      
      await updateStore(); 
    }
    asyncUpdateStore();

getDetails(storeValues)    //this is api call made based on updated store values above
       .then(()=>{...})    
    },[applyChange]);

Edit 1:

updateStore() method involves a dispatch call.

const updateStore=()=>{
 const data:IData={
   value1:valuestate1
   value2:valuestate2
}
dispatch(updateData(data));
}

Solution

  • In redux, all dispatches are synchronous. Using await has no effect there. If updateData() is an asynchronous action, then you may need look at the documentation of the middleware you are using, to handle async actions (i.e redux-thunk, etc).

    Usually, the middleware will provide 3 states ("pending", "success", "failed") that you can store in your redux store, and then read in your component. The logic flow could look like this.

        //example route that would store the current status of an async response
        const asyncState = useSelector(state => state.storeValues.status)
        const storeValues = useSelector(state => state.storeValues.data)
    
        useEffect(()=>{     
          //runs everytime applyChange changes
          dispatch(updateData(data));    
        },[applyChange, dispatch, updateData]);
        //runs everytime an async status changes, due to the api request done above
        useEffect(()=>{    
             //success indicates the promise resolved.
             if(asyncState === "success")
                getDetails(storeValues)    //this is api call made based on updated store values above.then(()=>{...})    
         },[asyncState]);
    

    To understand how async patterns work in redux, or see more examples, you can check out redux's own tutorial and docs here. The have a conceptual diagram of state flow, as well as a ton of guides.

    Note: dispatch actions should never be anything but synchronous, as reducers should not have side effects. Redux will throw errors and complain if an action is async, and you may see unexpected behavior in your store if async actions aren't handled outside reducers first.