State & Re-Renders
The problem
A UI needs to change in response to user interaction — a counter increments, a form field updates — and something needs to trigger the component function to run again and produce a new UI description whenever that internal data changes.
Why now
Variables and state already established a name bound to a value that can change; React's useState is that idea with one crucial addition — changing it doesn't just update a variable, it schedules the component function to run again, which is the entire mechanism that makes a UI 'live' instead of a one-time snapshot.
Mental model
Calling a state setter doesn't mutate anything in place — it tells React 'the next time you call this component function, use this new value instead,' and schedules a re-render. This is why state must be treated as immutable and replaced, not mutated: React's re-render decision is often just comparing the old and new value, and mutating in place would make old and new look identical.
Requires
- Components & JSXReact
State belongs to a specific component instance and drives what that component's function returns on its next call; you need the component-as-function model already established before 're-running the function with new state' is meaningful.
- Variables & StateProgramming Fundamentals
useState is a specialized variable binding whose change triggers a re-render, building directly on the general concept of a name bound to a changeable value.
Helps
- Mutability & ReferencesProgramming Fundamentals
Why state updates must create new objects/arrays rather than mutate existing ones is a direct consequence of reference semantics — React often compares references, so an in-place mutation looks unchanged.
Unlocks
Used in
- useState and every interactive React component
- Form inputs, toggles, counters — any UI that changes based on user action
- Understanding why array/object state must be replaced with a new copy, not mutated, on update
- React DevTools' Profiler, which visualizes when and why components re-render
Projects
- Build a counter component and a todo list component using useState, being careful to replace (not mutate) array state on every update
- Deliberately mutate array state directly instead of replacing it, observe that the UI fails to update, and explain why
Examples
- setCount(count + 1) schedules a re-render with the new count; the component function runs again from the top
- items.push(newItem); setItems(items) fails to trigger a UI update because the array reference didn't change — setItems([...items, newItem]) does
Resources
Mastery checklist
- I can explain that calling a state setter schedules a re-render rather than mutating in place
- I can update array and object state immutably (creating a new copy)
- I can explain why direct mutation of state can fail to trigger a re-render
- I can build a component with multiple independent pieces of state