skip to content

State and Context

How a React app decides where state lives, how it is shaped, and how it reaches the components that need it — colocation and lifting, reducers for complex transitions, context for sharing, and custom hooks for reuse. Interviewers push hard here because most React design questions ('how would you share this?', 'why does the whole tree re-render?') are really state-architecture questions.

part ofReactoverview, primer and where to startread it →
on this pageshow

explore

questions

page 2 of 2

A React component calls const [state, dispatch] = useReducer(reducer, buildInitialState(items)), where buildInitialState is expensive. What happens on every re-render, and how do you fix it?

level: middleimportance: should knowfreq 45%

basics

~20 s

buildInitialState(items) is an ordinary argument, so JavaScript evaluates it on every render even though React only uses its result on the first one. Pass the raw value plus the function as useReducer's third argument so React calls the initializer only on mount.

open as a page

In a React app, what does it mean that data fetched from an API is stale as soon as it arrives, and which events should make you revalidate it?

level: middleimportance: should knowfreq 45%

basics

~20 s

A response describes the server at the moment it was serialized; every instant after that it is an assumption. Revalidation triggers are a design decision per data type: after your own mutation, on remount, on tab focus or reconnect, on an interval, on user request, or on a server push.

open as a page

A React app's root has grown into eight nested context providers wrapping <App />. How do you tame that pyramid, and what does the nesting order actually mean?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Nesting order is real dependency order: a provider can only read contexts from providers above it. Tame the pyramid by moving providers down to the subtree that needs them, collecting the rest into one AppProviders component, and folding an ordered array with reduceRight where order is free.

open as a page

A React context holds an object with several unrelated fields, and a component that reads only one of them re-renders whenever any field changes. Why can't the component subscribe to just that field, and what do you do about it?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Context has no selector API: React compares the whole value with Object.is and notifies every reader, with no way to opt out per field. The structural fix is to split the value into several contexts along how often each part changes.

open as a page

You are publishing a shared custom hook, useFilters(), that returns the current filter state plus functions to change it. Consumers memoize child components and list your functions in dependency arrays. What identity guarantees should the hook's return value make, and how do you implement them?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Promise that the functions a hook returns keep the same identity for the life of the component, and that data changes identity only when it really changed. Implement stable functions with useCallback plus updater-form updates or a latest-value ref, so no state sits in their dependency list.

open as a page

Implement a React `useLocalStorage(key, initialValue)` hook that returns a value and a setter which also writes to localStorage. What does a naive implementation get wrong about reading storage, parsing, and server rendering?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Read storage in a lazy useState initializer, not on every render; wrap JSON.parse and every storage call in try/catch because parsing and quota both throw; support functional updates so the write matches the new state; and on the server, where localStorage does not exist, render the initial value and read storage after mount.

open as a page

Write a React `useOnClickOutside(ref, handler)` hook that closes a dropdown when the user clicks elsewhere. Which document event should it listen for, and how do you stop a new inline `handler` from tearing down and re-attaching the listener on every render?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Attach a document listener for pointerdown, ignore the event when ref.current contains event.target, and remove the listener in effect cleanup. Keep the handler in a ref refreshed each commit so the subscribing effect depends only on the ref, not on a handler identity that changes every render.

open as a page

After lifting selection state into a page component, the value and its onChange are threaded through four intermediate React components that never use them. How do you judge whether that is a real problem, and what would you change?

level: seniorimportance: should knowfreq 50%

basics

~20 s

Judge it by how many layers ignore the props and how often the contract changes; one or two hops are fine. The first fix is composition — let the owner build the elements and pass them as children or slot props, so the middle layers never see the data. Context comes after that.

open as a page

A teammate argues that filtering and sorting a 5,000-item list on every React render is wasteful and wants to keep the sorted result in useState, updated by an effect whenever the inputs change. How do you respond, and when is useMemo the right tool instead?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Storing the result adds a second source of truth, a stale frame and an extra render on top of the same computation, so it is strictly worse. Measure first; if the derivation is genuinely hot, use useMemo, which caches within the render and keeps one source of truth.

open as a page

A React team fixed a stale detail panel by putting key={selectedId} on their top-level page component, and now switching records also collapses the sidebar, jumps the scroll to the top and re-initialises an expensive chart. How do you decide which subtree the key actually belongs on?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Put the key on the smallest component that owns exactly the state that should die with the identity change. If that state is mixed with state that must survive, extract the identity-scoped part into its own component and key that one.

open as a page

A React submit flow uses a reducer whose switch is on action.type alone. A user double-clicks Submit, so a second SUBMIT arrives while the request is already in flight. How do you structure the reducer so only transitions that are legal from the current state are applied?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Make the transition a function of state and action, not of action alone: switch on the current status first and handle only the actions legal there, returning the state unchanged otherwise. A transition table keyed by state then action expresses the same rule as data.

open as a page

In a React useReducer, what is the difference between dispatching { type: 'setStatus', value: 'loading' } and dispatching { type: 'submitted' }, and why do reviewers push for the second style?

level: seniorimportance: should knowfreq 42%

basics

~20 s

The first is a remote-control setter: the component decides the new state and the reducer just writes it. The second names what happened and lets the reducer decide the consequences, so the rules live in one place and each user interaction is one action.

open as a page

A React UI shows a 'like' as applied immediately and sends the request in the background. What must that optimistic update keep hold of to be safe, and what has to happen when the request fails?

level: seniorimportance: should knowfreq 42%

basics

~20 s

An optimistic update must retain the pre-update value so it can be reverted, and must treat the server's response as the truth once it arrives. On failure it reverts to that snapshot and tells the user the action did not happen — a silent revert reads as the app losing their input.

open as a page

A React codebase has accumulated around thirty Context providers, and a tech lead proposes consolidating client state into a single external store. How would you evaluate that proposal, and what would you measure before committing?

level: principalimportance: should knowfreq 32%

basics

~20 s

Separate the contexts by role first: most are usually dependency injection of values that never change and should stay. Measure which ones actually update at runtime, how often, how many consumers need slices, and how many non-React readers exist — then migrate only those.

open as a page

In a React master-detail editor, remounting the detail pane with key={recordId} correctly clears it but also throws away unsaved edits when the user clicks another record and comes back. How do you decide between identity-keyed remount and keeping per-record draft state, and what does each choice commit you to?

level: principalimportance: should knowfreq 30%

basics

~20 s

Decide by whether losing the state is the intended product behaviour. If edits are disposable, keyed remount is the simplest correct answer. If they are work the user expects back, the draft must live above the keyed boundary, keyed by record id, and you own its lifetime.

open as a page

At what point does handling server data with plain React state — useState plus effects, or a value lifted into a provider — stop being the right home, and what would you weigh before adopting a dedicated caching layer?

level: principalimportance: should knowfreq 36%

basics

~20 s

It stops being right once the same entity is read from several places, writes must invalidate other screens, and freshness matters — because at that point you are reimplementing keys, deduplication, revalidation and cache lifetime by hand, inconsistently, in every feature.

open as a page

You own a shared React module that other teams consume — say a <FeatureFlagProvider> plus hooks. What do you decide about its public surface: what to export, whether the Provider owns its own state, and whether two instances may coexist?

level: principalimportance: nice to knowfreq 24%

basics

~20 s

Export the Provider and hooks, keep the context object private, and decide deliberately whether the Provider owns state or accepts it as a prop. Then state explicitly whether two mounted instances mean two independent scopes or a misconfiguration you should detect.

open as a page

A shared useDashboard() hook in your codebase takes an options object with eight boolean flags and returns fifteen fields, and every team is now afraid to change it. How do you decide where to split it, and what do you weigh when drawing hook boundaries in a shared library?

level: principalimportance: nice to knowfreq 30%

basics

~20 s

Split by concern and lifetime, not by size: each hook should own one source of truth or one subscription. Behaviour-selecting flags are the strongest signal that several hooks were fused, so extract those first and keep a thin composite for existing callers.

open as a page

Your React app has several hand-rolled useReducer state machines for wizards and async flows. When does moving them to a statechart library such as XState pay for itself, and when is it over-engineering?

level: principalimportance: nice to knowfreq 28%

basics

~20 s

A statechart library pays off when flows outgrow a flat status list — nested states, concurrent regions, guards and delays repeated across features, or a graph non-engineers must review. For one component with four states and six transitions, a plain reducer is cheaper and clearer.

open as a page

showing 31–49 of 49