When does the useState hook render?

The useState hook is probably the most popular and frequently used hook in React. There were a few questions I had about it. If a component had multiple useState hooks and an event handler did multiple state updates, will the component render multiple times? If a setState function did not change the state value, will the component be rendered again?

To answer these questions, I created a sample component. The first task is to measure the number of times a component renders.

Counter for component renders

Whenever a component renders, I want to increment a counter. To implement this, I made use of the useRef hook.

const countRef = useRef(0);
countRef.current += 1;

To display the counter, use a div like so:

<div>This component is rendered {countRef.current} times</div>

Will multiple state updates cause multiple renders?

To test this, create two state variables.

const [prop1, setProp1] = useState("Hello");
const [prop2, setProp2] = useState("World");

Add a button. Bind the click event to a handler.

<button onClick={multipleClick}>Multiple state updates</button>

Implement the multipleClick event handler. The function sets a random string to the state using multiple setState calls.

function multipleClick() {
    setProp1(makeRandomString());
    setProp2(makeRandomString());
}

The function makeRandomString is a simple utility I picked from StackOverflow.

function makeRandomString() {
  let result = "";
  const characters =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  const charactersLength = characters.length;
  const length = Math.ceil(Math.random() * 10);
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}

When I clicked on the button, multiple setState calls are triggered. And when I tested this, the counter incremented by 2, which suggests that multiple renders occurred.

For complex state management, it is better to use the useReducer hook. Using the useReducer hook will improve performance.

If state does not change, will it cause a render?

Create a button bound to an event handler.

<button onClick={sameClick}>Set same state as before</button>

The below event handler will not change the state value but just calls the setState function.

function sameClick() {
    setProp1((prop1) => prop1);
  }

When I clicked on the button, the counter did not increase. So, no renders occurred when setState does not change the value.

To try this live, check my CodeSandbox.