After some trial I discovered following problem occurs in strict mode. I would be interested if someone can explain why.
Take this simple example where inside render I am just scheduling a timeout which updates state:
Example:
let firstRender = true; // Normally I would use ref but I was playing with example
export default function App() {
let [data, setData] = React.useState({ name: 'Nick' });
// Schedule a timeout on first render
if (firstRender) {
setTimeout(() => {
console.log('Running');
setData((ps) => ({
...ps,
name: 'Paul',
}));
}, 1000);
}
console.log('Running render');
firstRender = false;
return (
<div>
<h1>{data.name}</h1>
<p>Start editing to see some magic happen :)</p>
</div>
);
}
If you run this example without Strict mode, then you will see "Paul" on screen after one second, as I was expecting.
If you use Strict mode, it will always show "Nick" on screen. Idea why?
Note: it seems using useRef
instead of the global variable firstRender
fixes this problem also in Strict mode. This seems to happen because ref
was set in first render, and its value also got discarded (see also the answer).
State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.
Whenever we update the state using the setState() method it re-renders the current component and its child components. When we call the setState function it receives the latest state snapshot. Then we can use it inside the setState() function and return the new value to which we want to update the new state value to.
To update our state, we use this. setState() and pass in an object. This object will get merged with the current state.
StrictMode is a tool for highlighting potential problems in an application. Like Fragment , StrictMode does not render any visible UI. It activates additional checks and warnings for its descendants. Note: Strict mode checks are run in development mode only; they do not impact the production build.
This is due to the fact that strict mode intentionally invokes your function component body twice (when in dev mode) to help spot unintended side effects.
On the second invocation, your firstRender
variable is false
so your setTimeout doesn't run.
Important to note that this second invocation isn't just a re-render like you'd get from a state update. It's a second invocation of the entire component body. State is not preserved. React invokes your component function once, discards the result, and invokes it a second time to get the output.
From the docs:
Because the above methods might be called more than once, it’s important that they do not contain side-effects.
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:
- Function component bodies
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With