This is the React code that I have for a page:
function ExportViewerPage(): JSX.Element {
const [hasPrinted, setHasPrinted] = useState(false);
if (!hasPrinted) {
setHasPrinted(true);
console.log("Inside if loop, hasPrinted: ", hasPrinted)
setTimeout(() => {
console.log("Executing setTimeout: ", hasPrinted)
});
}
return (<div>Page</div>)
}
export default ExportViewerPage;
Ultimately, the code should execute the code in the setTimeout function once. However, it actually executes twice as seen in the console here:
Inside if loop, hasPrinted: false
Executing setTimeout: false
Executing setTimeout: false
The weird thing is that the console log immediately before the setTimeout function only executes once, so the setTimeout is not being called twice and hasPrinted is getting set correctly. This is happening on both Chrome and Firefox.
I did notice that if I turn reactStrictMode off in the next.config.js file, the setTimeout will only fire once. But I am still confused as to why the setTimeout is firing twice with reactStrictMode on but the console log immediately above it is only logging once.
>Solution :
This behavior is caused by React’s strict mode, which can execute some code twice in development mode to detect potential issues. One of the effects of strict mode is that some side-effects may be executed twice, including some lifecycle methods like componentDidMount.
In your case, the setTimeout function is a side-effect that is being executed twice because it is inside the component body. One possible solution would be to move it into a useEffect hook with an empty dependency array, so that it only gets executed once when the component mounts:
function ExportViewerPage(): JSX.Element {
const [hasPrinted, setHasPrinted] = useState(false);
useEffect(() => {
if (!hasPrinted) {
setHasPrinted(true);
console.log("Inside useEffect, hasPrinted: ", hasPrinted)
setTimeout(() => {
console.log("Executing setTimeout: ", hasPrinted)
});
}
}, []);
return (<div>Page</div>)
}
export default ExportViewerPage;
This code will only execute the setTimeout function once when the component mounts, regardless of whether the strict mode is enabled or not.
https://react.dev/reference/react/StrictMode#fixing-bugs-found-by-double-rendering-in-development