skip to Main Content

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


  1. 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), the useEffect would only execute it when initializing:

    useState(generateRandomColor);
    

    Pass an anonymous function is identical. You pass a function that you want the useEffect to call only on init.

    Login or Signup to reply.
  2. What is going on behind the scenes in JavaScript?

    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. But useState(generateRandomColor()) means this:

    • Run generateRandomColor, get its return value
    • Pass that return value into useState

    Since useState will ignore the passed value after the first render, that means the call to generateRandomColor 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 do useState(generateRandomColor); to pass the function to useState, which will call it the first time and ignore it other times. (If the function needed parameters, then you’d need a wrapper function.)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search