Back to all terms
S1S2S3
State & Archintermediate

Component-Level vs Global State

The architectural decision of whether state should live within a single component, be lifted to a shared ancestor, or be placed in a global store based on its scope and consumer count.

Also known as: Local vs Global State, State Colocation, State Placement Strategy

Description

One of the most impactful decisions in frontend architecture is determining where state should live. Component-level (local) state is owned by a single component and managed via useState, useReducer, or framework equivalents. It is the simplest and most performant option because updates only affect the owning component. Lifted state moves data to a common ancestor of the components that need it, passing it down via props. Global state (Redux, Zustand, Context) makes data accessible to any component in the tree without prop drilling.

The principle of state colocation dictates that state should live as close as possible to where it is used. Form input values, toggle states, local UI animations, and transient interaction state should almost always be local. Data shared between sibling components should be lifted to their nearest common parent. Only truly global concerns—authenticated user, theme preferences, feature flags, notification queues—belong in a global store. Server-cached data (API responses) should be managed by a dedicated server-state library (React Query, SWR, Apollo Client) rather than stuffed into a global store.

The most common mistake in frontend architecture is over-globalizing state. Putting everything in Redux or Context causes unnecessary re-renders across the component tree, creates coupling between unrelated features, and makes components impossible to reuse or test in isolation. A well-architected application typically has: local state for UI interactions, React Query or equivalent for server state, a small global store for auth and preferences, and URL state (search params, path) for navigation-related state. Each category has different caching, persistence, and synchronization requirements.

Prompt Snippet

Enforce a strict state placement hierarchy: 1) useState/useReducer for all component-scoped UI state (form inputs, toggles, modals), 2) React Query with queryClient for all server-fetched data with staleTime of 5 minutes for list queries and Infinity for reference data, 3) Zustand with selectors for global client state (auth session, feature flags, toast queue), 4) URL search params via nuqs or next/navigation for filterable/shareable state. Establish an ESLint rule or PR review checklist that flags any server response data being stored in Zustand or Context, and document the decision tree in an ADR.

Tags

state-managementfrontend-architecturereactperformancebest-practices