Capítulo 63 de 116

Chapter 63: useState

Core Idea

useState(initialState) is the API reference for the state mechanic built up conceptually across Ch 21/23/24: returns [value, setValue], where initialState is only used on the very first render and setValue schedules a re-render with a new snapshot rather than mutating in place.

Key Concepts

  • Signature: const [state, setState] = useState(initialState). If initialState is expensive to compute, pass a function (useState(() => expensiveInit())) instead of calling it inline — React only calls that initializer function once, on the first render, whereas an inline call would re-run (and be discarded) every render.
  • Two forms for setState: a direct next value (setState(5)), or an updater function (setState(prev => prev + 1)) — the updater form is required when queuing multiple updates to the same state within one handler that must compound (Ch 24).
  • setState bails out if the new value is Object.is-equal to the current one — calling the setter with the identical value it already holds skips the re-render entirely, a built-in optimization, not something you need to guard against yourself.
  • Never mutate state directly. Objects/arrays in state must be replaced with new references (Ch 25/26) — state.field = x; setState(state) looks like it should work but won't reliably trigger updates and breaks other guarantees.
  • State persists only for the component instance's tree position (Ch 30) — remounting (different type or a changed key at that position) discards it entirely; unmounting removes it permanently.

Code Examples

const [todos, setTodos] = useState(() => createInitialTodos()); // lazy init, runs once
const [count, setCount] = useState(0);
// compounding updates within one handler need the updater form:
setCount(c => c + 1);
  • What it demonstrates: lazy initialization (avoiding re-running an expensive setup function every render) alongside the updater-function form for compounding updates.

Key Takeaways

  1. Use the lazy-initializer function form whenever the initial value requires real computation — a plain function call as the argument re-runs (wastefully) every render even though only the first result is ever used.
  2. Reach for the updater-function form of setState whenever the next value depends on the previous one, especially when multiple updates might queue within one handler.
  3. setState is a request to re-render with new state, not an in-place mutation — treat every state value (especially objects/arrays) as fully replaceable, never edited.

Connects To

  • Ch 21 (State: A Component's Memory), Ch 23 (State as a Snapshot), Ch 24 (Queueing a Series of State Updates): the full conceptual treatment this reference formalizes.
  • Ch 25/26 (Updating Objects/Arrays in State): the immutability discipline this Hook requires for non-primitive state.