Reputation: 51
Why setState(contains another setState inside) after promise be called twice?
Demo code:
https://codesandbox.io/s/setstate-issue-v1fpv
const App = () => {
const [a, setA] = useState(0);
const [b, setB] = useState(0);
const onClick = async () => {
await new Promise((r) => setTimeout(r));
// when after promise, setB called twice
// remove promise, setB called once
setB((prevB) => {
console.log("setB");
setA((prevA) => prevA + 1);
return prevB + 1;
});
};
return (
<>
{a} | {b} | <button onClick={onClick}>+1</button>
</>
);
};
Upvotes: 1
Views: 95
Reputation: 51
For those who also confused, here is the answer from React docs:
Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:
- Class component constructor, render, and shouldComponentUpdate methods
- Class component static getDerivedStateFromProps method
- Function component bodies
- State updater functions (the first argument to setState)
- Functions passed to useState, useMemo, or useReducer Note:
This only applies to development mode. Lifecycles will not be double-invoked in production mode.
https://reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects
https://github.com/facebook/react/issues/21114#issuecomment-808697394
Upvotes: 1