Edit
Okay my bad, I guess the response is simple. It’s a javascript matter. I am not passing a function to useState but actually I am re-executing it everytime. So yeah what I am seeing is normal.
I will let my question here anyway.
A codesandbox example will follow.
Question :
Could someone please explain to me why React re-execute the inner function in a useState (or useRef) despite the returned value will be completely ignored (except the first execution) ? Is this the expected behaviour of useState ?
Explanation :
I mean why I see this console log here after each re-render
const [count, setCount] = React.useState((function(){
console.log('Executed !');
return 5;
})())
I used to think this inner function (or values) is the equivalent of a Class Parameters or Component Constructor but it’s obviously not the case.
Returning a simple value does the job of course : React.useState(5).
But imagine using a third-party class which works with static values at some point or you simply don’t want to re-execute it over and over again after each re-render ?
A possible fix for this is using useEffect with an empty dependency. (The equivalent of componentDidMount)
But I am asking about the purpose of this execution ?
let count = 0; // Number of component renders
const Test = (props) => {
const [innerCount, setCount] = React.useState((function(){})(
console.log('Executed !'); // Executed after each re-render
count = count + 1;
return count;
));
return innerCount; // Will be always 1 !
}
Why the anonymous function will be executed if the returned value is always 1 = the first returned value ?! What’s the purpose of this execution ?
This is an example on CodeSandbox
>Solution :
This isn’t React-specific behaviour, it’s just what Javascript – and almost every mainstream programming language – does.
Before calling a function, it has to evaluate its arguments in order to know what to pass in.
Yes, it so happens that React.useState is a function that often "ignores" its argument. (I’m not familiar with precisely how it’s implemented – clearly it isn’t as simple as that as it does need to know when it’s the first time it’s being executed in that particular component instance, because in that case that value is used and returned.) But the browser Javascript engine can’t possibly know that or optimise it away.
To prove this isn’t anything to do with React, I can do this:
function ignoresArgument(x) {
return 1;
}
for (let i = 0; i < 20; i++) {
ignoresArgument(
(function(y) {
console.log("I don't need to be executed, but Javascript doesn't know that so I will be executed 20 times");
return 2;
})(1)
);
}