I have been taking a React performance training course and this code base is used as an example: https://github.com/stevekinney/wordman/blob/main/src/components/application.jsx#L10
When we call the function inside of useState()
it is called on every re-render even though the actual value of correctAnswer
does not change. If the function was large and complicated, this could cause a performance issue.
e.g.
const [correctAnswer, setCorrectAnswer] = useState(generateRandomColor());
To avoid this, I have to wrap it in an anonymous function or not invoke the function within the useState
hook.
e.g.
const [correctAnswer, setCorrectAnswer] = useState(() => generateRandomColor());
const [correctAnswer, setCorrectAnswer] = useState(generateRandomColor);
Why is that? What is going on behind the scenes in JavaScript?
2
Answers
When you call the function explicitly
generateRandomColor()
, the function is called on each render. The function is called because the wrapping function component is executed, and you manually execute the function (note the parentheses).When you pass the function to
useState
without calling it (note the lack of parentheses), theuseEffect
would only execute it when initializing:Pass an anonymous function is identical. You pass a function that you want the
useEffect
to call only on init.It’s not really anything to do with the language, it’s just how React function components and
useState
work. Your function is called every time the component needs to render, but as you said,useState
only uses the initial value you give it on the first render — after that, it completely ignores what you give it. ButuseState(generateRandomColor())
means this:generateRandomColor
, get its return valueuseState
Since
useState
will ignore the passed value after the first render, that means the call togenerateRandomColor
is pointless on any render but the first.That’s why
useState
allows you to pass in a function instead: It will only call the function on the first render. So if the function doesn’t have any parameters, you can douseState(generateRandomColor);
to pass the function touseState
, which will call it the first time and ignore it other times. (If the function needed parameters, then you’d need a wrapper function.)