WittCode💻

React Multiple State Updates

By

Learn how to handle multiple React state updates including what batching is, component re-rendering, and updater functions.

Table of Contents 📖

Handling Multiple State Updates

When a state variable is changed, React will place the render in a queue as opposed to re-rendering the component right away. This is because React waits until all code has been ran before processing a state update. To demonstrate, the code below changes some state and logs to the console when a button is clicked.

import {useState} from 'react';
  
const App = () => {
  console.log('Rendering App');
  const [favFood, setFavFood] = useState('');
  const [favSport, setFavSport] = useState('');
  const [favNumber, setFavNumber] = useState('');

  /**
   * These state updates don't cause a re-render
   * until this entire function is finished. 
   */
  const setFav = () => {
    setFavFood('Pizza');
    setFavSport('Football');
    setFavNumber(100);
    console.log('Hello there!');
  };

  return (
    <>
      <h1>{favFood}</h1>
      <h1>{favSport}</h1>
      <h1>{favNumber}</h1>
      <button onClick={setFav}>What's Your Fav?</button>
    </>
  );
};

Notice how React runs all the code in the setFav function before re-rendering. This is evident by the logging of "Hello there!" to the console even after all the SetState calls have been ran.

Batching

This action above is known as batching. Batching is the process of grouping multiple state updates into a single render. In other words, batching ensures React processes state updates after all the code in an event handler has been ran. Batching speeds up React apps and avoids incomplete re-renders.

Batching the Same State Variable

Above, we were working with 3 different state variables. Now, lets focus on working with 1. Batching the same state variable can be confusing for some developers because calling the same SetState function multiple times in a row will not update the state multiple times. In the code below, clicking the button will increment the count variable three times.

import {useState} from 'react';

const App = () => {
  const [count, setCount] = useState(0);

  /**
   * Running this function increments count by 
   * 1, not 3. This is because state is a
   * fixed value per render.
   */
  const increment = () => {
    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
  };

  return (
    <>
      <h1>{count}</h1>
      <button onClick={increment}>Increment</button>
    </>
  );
};

Lots of developers expect the count variable to be incremented by 3. For example, clicking it once makes count 3, then 6, then 9, etc. However, this is not the case. In reality, the output will be 0, then 1, then 2, etc. This is because each render has a fixed state value. In other words, each time a component function is called, it will have the same state value throughout.

Updater Functions

However, we can update a state variable multiple times in one render by passing a function to the SetState function, known as an updater function.

import {useState} from 'react';

const App = () => {
  const [count, setCount] = useState(0);

  /**
   * These are updater functions. Now it will
   * add 3 to count each time this function is called.
   */
  const increment = () => {
    setCount(c => c + 1);
    setCount(c => c + 1);
    setCount(c => c + 1);
  };

  return (
    <>
      <h1>{count}</h1>
      <button onClick={increment}>Increment</button>
    </>
  );
};

Updater functions update the state value as opposed to replacing it. This is because updater functions receive the current state value as an argument.