Drills Repository
23 Drills · All Belts · state-basics
Child cannot directly modify parent state
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 variables vs state persistence
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.
When state is unnecessary
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 triggers a re-render
React schedules re-renders when state updates are made through React APIs like a state setter. Regular variables and external values are not tracked by React's rendering system.
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.
Independent component state
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.
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.
Derived state redundancy
A value that can always be recalculated from existing state during render is redundant as separate state, since storing it separately creates a risk that some update path forgets to keep it in sync. React naturally recalculates derived expressions like fullName on every re-render.
Object.is state bailout
React compares previous and next state using Object.is, which checks reference identity rather than deep contents. Passing the same object reference back into a setter means React sees no change and skips re-rendering.
Selected object duplication
Updating an item in an array creates a new object for the edited entry, but a separately stored selectedItem still points to the old reference, creating duplicated and diverging data for the same conceptual item. Storing only a selectedId avoids this by letting the selected item always be derived from the current array.
Grouping related state variables
When multiple pieces of state always change together, keeping them separate increases the risk of forgetting to update one of them. Grouping them into a single state object makes that relationship explicit, though React still requires immutable copying rather than automatic merging of nested fields.
Storing functions in state
useState treats a function argument as a lazy initializer and calls it to compute the initial state value, rather than storing the function itself. To store a function as the state value, it must be wrapped as () => someFunction so React receives a function that returns the function.