Using state after dispatch has fired

Viewed 3240

I need to be able to preform an action right after I update my useReducer state with dispatch. But dispatch runs async so when I run my next piece of code, it uses the old state before dispatch was supposed to update it.

What I've tried is using useEffect(()=>{},[state]), but that just runs every time state updates. I need to preform certain actions based on conditions... not just every time state updates.

// Let's update some stuff on the server with new data!
  const handleFinishOrder = () => {

    dispatch({ type: "finish-order", payload: id }); // Set some fields to null

    socket.emit("request-update-live-data", state); // Old state gets sent to server :(
  };

I expect the state to be updated when I go emit it off to the server but the actual state that gets sent is the old state.

2 Answers

dispatch is handled asynchronously and API does not provide any way of executing a piece of code after the dispatch has been executed.

In fact, it specifically warns if you try to pass a callback function to dispatch:

Warning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().

So, you should do socket.emit in a useEffect with appropriate dependency list.

Alternatively, you can do it in your reducer function for specific action type.

I was running into the same problem I used the useEffect hook to solve this problem

const handleFinishOrder = () => {
    dispatch({ type: "finish-order", payload: id });  
 };
  
  
useEffect(() => {
    socket.emit("request-update-live-data", state);
}, [state]);

this is only suitable in specific cases because the operation will be performed whenever the state is updated, in most cases the right solution is to use the useEffect and useState hooks

const [someState, setSomeState] = useState("ainitialState");


const handleFinishOrder = () => {
    setSomeState("new value")  
 };
  
  
useEffect(() => {
    socket.emit("request-update-live-data", someState);
}, [someState]);

Related