State

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

State

Components often need to change what’s on the screen as a result of an interaction. Typing into the form should update the input field, clicking “next” on an image carousel should change which image is displayed, clicking “buy” should put a product in the shopping cart.

Components need to “remember” things: the current input value, the current image, the shopping cart. In React, this kind of component-specific memory is called state.

Why regular variables aren’t enough

You might be tempted to use a regular JavaScript variable to remember data:

function Counter() {
  let count = 0; // Regular variable

  function handleClick() {
    count = count + 1;
    console.log(count); // Logs 1, 2, 3... but UI doesn't update!
  }

  return <button onClick={handleClick}>Clicked {count} times</button>;
}

The code above won’t update the UI. Why?

  1. Local variables don’t persist between renders. When React renders this component a second time, it renders it from scratch—it doesn’t consider any changes to the local variables.
  2. Changes to local variables won’t trigger renders. React doesn’t realize it needs to render the component again with the new data.

To update a component with new data, two things need to happen:

  1. Retain the data between renders.
  2. Trigger React to render the component with new data (re-rendering).

The useState hook provides both of these things.

Interview Questions

Q: Exactly how does React know when to trigger a re-render after a state update?
A: When you call a state setter, React compares the newly provided state value with the current state value using the Object.is() algorithm. If the references are identical (e.g. you pushed to an array but passed the same array reference back), React bails out and will NOT re-render. If they are different, it queues a render.