Description
React version: 17.0.2
I ran in to this interesting dynamic that I cannot explain today.
- The code sets some initial state, which is a random number, and logs this initial value.
- It converts the number to a string using
useMemo
, which logs the number it is converting, and is dependant on that number (not the string). And - when the component is mounted, I force a re-render by changing a boolean state once.
The result is that the initial value of the number is changed (and the log is output) so you see the number being set twice to two different values - this only happens in StrictMode
. It is surprising. Is it expected?
You also see the useMemo
being computed ONCE - only the first time. So seemingly it does not recompute a new string value.
BUT, the output in the HTML is the correct and shows the stringified value of the second number.
So what is happening here? Is the console log swallowed? Is useMemo
behaving correctly, and more importantly, is the initialValue
of useState
supposed to change like that?
Steps To Reproduce
export default function App() {
const [rand] = useState(Math.random());
const [, setState] = useState(false);
console.log(`Number: ${rand}`);
useEffect(() => {
setState(true);
}, []);
const text = useMemo(() => {
console.log(`Computing text from ${rand}`);
return rand.toString();
}, [rand]);
return (
<div className="App">
<h1>Rand: {rand}</h1>
<h1>Text: {text}</h1>
</div>
);
}
And wrap your app in StrictMode
Link to code example:
https://codesandbox.io/s/strict-mode-random-bug-ml3gv
The current behavior
initial state computed twice.
usememo seemingly not run twice
The expected behavior
Initial state computed once?
Or usememo runs twice?