# Batching and Updater Functions — React

Source: https://www.skillbyai.com/en/react/s-batch

> Why three increments can add one.

## State is a snapshot per render

Inside one render, a state variable is a fixed **snapshot**. `setA(a + 1)` three times in the same handler uses the same `a` each time, so the result is +1. React also **batches** updates from the same event into one re-render. When the next value depends on the previous one, pass an **updater function**: `setB(x => x + 1)` queues updates that each receive the latest value, giving +3.

## Snapshot versus updater functions, run

I ran this with React 19.3 and react-dom 19.3 on Node.js 22, compiling JSX with esbuild 0.28. Browser-style examples use jsdom 29 as a fake DOM (imported from a small setup-dom.mjs file) and act() to apply updates. One click calling setA(a + 1) three times leaves a = 1; one click calling setB(x => x + 1) three times gives b = 3. The two clicks together cause just 2 renders because updates in each handler are batched.

```jsx
import "./setup-dom.mjs";   // test setup: jsdom provides a browser-like DOM in Node
import { useState, act } from "react";
import { createRoot } from "react-dom/client";

let renders = 0;
function Demo() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);
  renders++;
  return (
    <>
      <button id="stale" onClick={() => { setA(a + 1); setA(a + 1); setA(a + 1); }}>a = {a}</button>
      <button id="updater" onClick={() => { setB(x => x + 1); setB(x => x + 1); setB(x => x + 1); }}>b = {b}</button>
    </>
  );
}
const root = createRoot(document.getElementById("root"));
await act(() => root.render(<Demo />));
renders = 0;
await act(() => document.getElementById("stale").click());
await act(() => document.getElementById("updater").click());
console.log(document.getElementById("stale").textContent, "|", document.getElementById("updater").textContent);
console.log("renders for two clicks (three updates each):", renders);
```

Output:

```
a = 1 | b = 3
renders for two clicks (three updates each): 2
```

## Use updaters for counters and toggles

Whenever the new state is computed from the old state, prefer the updater form.

**Quiz:** What does calling setCount(count + 1) three times in one click do?

- [ ] Throws an error
- [ ] Increases by 3
- [x] Increases count by 1, because count is the same snapshot each time
- [ ] Resets count to 0

*Answer:* Increases count by 1, because count is the same snapshot each time. Use setCount(c => c + 1) for sequential updates.
