Duma - Stefano Gombi
Duma - Stefano Gombi

Reputation: 472

useState conflicts with async operations in React

In a React functional component with the useState hook I don't know how to run multiple async operations without having conflict on the final result.

If the initial state is an object and every async operation performs a change on a given key, it's possible to use the spread operator in order to set a new state. Example:

const [oldState, setNewState] = React.useState({ /* something */ });
const asyncOperation = async () => {
   await somethingAsync();
   setNewState({
      ...oldState,
      key: 'newValue',
   });
};

The problem emerges when more of those operations run in the same time: the oldState used during setNewState may be changed by the end of another async function, but some updates of the state may be lost when the last async operation performs his setNewState since the reference to oldState can point to an old version of the variable.

Here's a demo: try to click every button in a row and, in the end, some of them will (probably) result still loading.

How can I avoid this problem without leaving react hooks?

Upvotes: 8

Views: 4044

Answers (1)

Joseph D.
Joseph D.

Reputation: 12174

For async operations, you need to make use of the previous state using the updater function.

setNewState((previousState) => ({
  ...previousState,
  key: 'newValue',
}));

In here, oldState is != previousState.

Upvotes: 10

Related Questions