Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent race conditions with react useState hook

I have a component that uses hooks state (useState) api to track the data.

The object looks like this

const [data,setData] =  React.useState({})

Now I have multiple buttons which make API requests and set the data with the new key

setAPIData = (key,APIdata) => {

    const dup = {
      ...data,
      [key]:APIdata
    }
    setData(dup)
}

Now if I make multiple requests at the same time , it results in race conditions since setting state in react is asynchronous and I get the previous value.

In class-based components, we can pass an updater function to get the updated value, how to do this hooks based component.

like image 716
sidhant manchanda Avatar asked Feb 12 '20 13:02

sidhant manchanda


People also ask

How do you avoid race condition in React?

The cleanup function is executed before executing the next effect in case of a re-render. The difference is that the browser cancels the request as well since we are using AbortController. And those are the two ways we can avoid race conditions while making API requests using React's useEffect hook.

What is the practice to avoid when using React Hooks?

Hooks should not be called within loops, conditions, or nested functions since conditionally executed Hooks can cause unexpected bugs. Avoiding such situations ensures that Hooks are called in the correct order each time the component renders.

How do I stop useState from rendering?

The most straightforward approach to preventing state update re-renders is by avoiding the state update entirely. This means making sure that the setState function is not called unless strictly necessary.

Can React Hooks be called conditionally?

The error "React hook 'useState' is called conditionally" occurs when we use the useState hook conditionally or after a condition that may return a value. To solve the error, move all React hooks above any conditionals that may return a value.


1 Answers

You must use setData with a function as its argument. Then it will always get the previous state, no matter what order it will be called.

const [data,setData] =  React.useState({})
setData(prevData => ({
  ...prevData,
  [key]: APIdata
}));

Documentation: somewhat hidden in hook api reference. reactjs.org/docs/hooks-reference.html#functional-updates

like image 160
Peter Ambruzs Avatar answered Sep 23 '22 01:09

Peter Ambruzs