react
react copied to clipboard
Bug: out of order application of useState changes
After updating my app to React 18 I had problem with outdated arguments passed to components
I created simple code example with the problem:
- I have 2 states
const [done, setDone] = useState(false);
(inside hook) andconst [ids, setIds] = React.useState([])
- I call
setIds([1,2,4])
(inside await, but it's executed immediately, as we see in console) and thensetDone(true)
- then component is rerendered with updated
done
but originalids
- then component is rerendered, but with both states updated
React version: 18.2.0, 18.3.0-next Link to code example: https://codesandbox.io/s/purple-dust-ww9hjm?file=/src/index.jsx
The current behavior
In the example after clicking run:
Inner
is rerendered with done: true
, but without updated ids
.
FormikLike
is created with empty ids
.
[]
is displayed under button.
The expected behavior
First Inner
rerender should have updated ids
state.
FormikLike
should be created with non-empty ids
.
[1,2,4]
is displayed under button.
It workied this way in React 17.
In https://stackoverflow.com/a/48610973 @gaearon wrote:
But can you trust React to update the state in the same order as setState is called for the same component?
Yes.
Answer was for class components, but I hope the same is true for multiple useState hooks in single function component.
Smaller repro: https://codesandbox.io/s/cocky-fermat-qoiel3
Basically two setState
calls that are separated by a microtask are not applied in-order
@gaearon Can you have a look?
In https://github.com/reactwg/react-18/discussions/2 you wrote
Does this break anything for Hooks? If you’re using Hooks, we expect automatic batching to "just work" in the vast majority of cases. (Tell us if it doesn't!)
This looks to be the same as #24649 so let's consolidate there.