Drills Repository
23 Drills · All Belts · state-basics
Callback Props After Lifting State Up
State belongs to the component where it is declared, so only that component can update it directly. Since activeIndex lives inside Accordion, child panels must request changes through callback props passed down from the parent.
Local Variable Update Inside a Click Handler
React re-renders a component by calling its function again from scratch, so ordinary local variables are recreated on every render and their previous values are not preserved. React only schedules a new render when a state setter or similar React API is called.
Same Component Rendered Twice With useState
State is tied to a specific component instance at a position in the rendered tree, not to the component function definition itself. Each Gallery instance holds its own isolated state, so clicking Next in one instance updates only that instance's index.
Choosing Between useState And A Local Variable
State is useful when data must persist across renders and affect rendering output. In this case, the name is only needed temporarily inside a single event handler, so a regular variable is simpler and avoids unnecessary re-renders.
What Actually Re-Renders A Component
React only schedules a re-render when a component's state changes through an official React API such as a state setter function. Ordinary local variables, external constants, and closures over old values are invisible to React's rendering system and never cause a re-render on their own.
Controlled vs uncontrolled component
A controlled component receives its important state through props instead of owning that state internally. In the accordion example, the parent controls which panel is active through isActive and event handler props.
Initializer function vs immediate call
Passing a function reference to useState creates an initializer React calls only once, while invoking the function immediately runs it on every render even though React discards the extra result. Here, useState(createTodos) treats createTodos as the initializer, but useState(createTodos()) calls createTodos on every render.
Synchronizing state between components
Lifting state up establishes a single source of truth, which keeps data flow predictable and avoids synchronization bugs between components. Using Effects to mirror state between components instead often introduces unnecessary complexity and cascading render chains.
isSending and isSent as Separate Booleans
Multiple independent boolean flags can combine into states that should never coexist, since nothing prevents them from being set contradictorily at the same time. Here, isSending and isSent could both be true at once, whereas a single status value restricts the form to exactly one valid state at a time.
useState Initialized From a Color Prop
useState(initialValue) only reads its initial value on a component's first render; it never re-runs automatically when props or other values change afterward. Here, const [color] = useState(props.color) captures props.color only once, so later changes to the color prop never update the color state variable.
Packing List Storing Items Total and Packed
Values that can be recalculated from existing state during render should not be stored as separate state, since redundant copies can drift out of sync. Here, total and packed can be derived from the items array during render, so keeping them as separate state risks drifting out of sync with the actual list.
Multiple selection state structure
Multiple independent selections are best represented as a collection of stable identifiers rather than as one flag or string, since collections scale naturally as the list grows. Here, replacing the single selectedId with an array or Set of selected IDs lets the mail client track any number of selected letters, with Sets also giving fast membership checks.