Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 228
Duma - Stefano Gombi Avatar asked Sep 26 '19 07:09

Duma - Stefano Gombi


People also ask

Is useState async in React?

TL;DR: useState is an asynchronous hook and it doesn't change the state immediately, it has to wait for the component to re-render.

Is React setState Hook async?

React useState hook is asynchronous!

Why useEffect should not be async?

This WORKS, but you should avoid it. Why? Because React's useEffect hook expects a cleanup function returned from it which is called when the component unmounts. Using an async function here will cause a bug as the cleanup function will never get called.

Why does the React useState Hook not update immediately?

The answer: They're just queues setState , and React. useState create queues for React core to update the state object of a React component. So the process to update React state is asynchronous for performance reasons. That's why changes don't feel immediate.

How to render a page refresh using async function in react?

You could possibly use a React Ref to store the state of the state variable. Then update the state variable with the react ref. This will render a page refresh, and then use the React Ref in the async function.

What is the usestate hook in react?

This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. Much like setState in Class components created by extending React.Component or React.PureComponent, the state update using the updater provided by useState hook is also asynchronous, and will not be reflected immediately.

What is the use of usestate in react?

This is a way to “preserve” some values between the function calls — useState is a new way to use the exact same capabilities that this.state provides in a class. Normally, variables “disappear” when the function exits but state variables are preserved by React.

What is the difference between setState and initialState in react?

During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState). The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.


1 Answers

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.

like image 143
Joseph D. Avatar answered Sep 23 '22 05:09

Joseph D.