Next.js Curriculum
MediumComponent Boundaries100% Free25 min read

State Management & Context Architecture in RSC

The 30-Second Interview Answer

In an RSC-first architecture, server state is managed through the URL and Server Components, eliminating redundant global stores. React Context and client stores (Zustand, Redux) are restricted to Client Components for interactive UI state, initialized with server data via props or provider wrappers without hydration mismatches.

Learning Objectives

Design modern state architectures dividing server state, URL state, and client UI state.

Explain why React.createContext is prohibited in Server Components.

Initialize client stores (Zustand, Redux) with server data safely.

Use URL search params as the primary server state coordinator.

Prerequisites & Background Knowledge
React Context APIGlobal state storesRSC boundaries

Why Interviewers Care

Core architecture question for mid-to-senior frontend roles designing scalable frontend systems.

The Challenge

How does state management change in a React Server Components architecture? Compare the roles of URL state, Server Components, and client state libraries like Zustand or Redux.

Code Architecture & Implementation

1// 1. SERVER STATE COORDINATION VIA URL
2// Filters, pagination, and sorting belong in the URL!
3// app/products/page.tsx (Server Component)
4import { ProductFilterBar } from './ProductFilterBar';
5import db from '@/lib/db';
6
7export default async function ProductsPage({
8 searchParams,
9}: {
10 searchParams: Promise<{ category?: string; sort?: string }>;
11}) {
12 const { category = 'all', sort = 'price_asc' } = await searchParams;
13
14 // Database query driven by URL state! Shareable, bookmarkable, zero client Redux!
15 const products = await db.product.findMany({
16 where: category === 'all' ? {} : { category },
17 orderBy: { price: sort === 'price_asc' ? 'asc' : 'desc' },
18 });
19
20 return (
21 <div>
22 <ProductFilterBar activeCategory={category} activeSort={sort} />
23 <ProductList items={products} />
24 </div>
25 );
26}
27
28// 2. CLIENT UI STATE (Cart drawer, modal visibility, ephemeral UI)
29// components/cart-store.ts
30import { create } from 'zustand';
31
32interface CartUIState {
33 isDrawerOpen: boolean;
34 toggleDrawer: () => void;
35}
36
37export const useCartUIStore = create<CartUIState>((set) => ({
38 isDrawerOpen: false,
39 toggleDrawer: () => set((s) => ({ isDrawerOpen: !s.isDrawerOpen })),
40}));

Architectural Explanation

The Three Tiers of State in Modern Next.js

  1. Server State (Server Components & Database):
    • In legacy SPAs, developers fetched data on the client and stored it in Redux/React Query.
    • In App Router, Server Components query data directly. The server is the state cache.
  2. URL State (Search Parameters):
    • Filters, search queries, pagination, and active tabs belong in the URL (?search=shoes&page=2).
    • Benefits: URLs are shareable, bookmarkable, preserve browser back/forward history, and allow the server to render filtered HTML immediately.
  3. Ephemeral Client UI State (Zustand, Context, useState):
    • Reserved strictly for interactive UI behaviors: dropdown open/closed, modal visibility, audio player playback, and optimistic form edits.
    • Client stores should be localized to Client Components and should not duplicate data already available in the Server Component tree.

Common Mistakes & Anti-Patterns

Creating a monolithic global Redux store for all API data, bypassing RSC caching and performance benefits.

Putting filter and pagination state in client memory instead of URL search params.

Initializing client stores with server data using useEffect, which causes noticeable hydration mismatches and layout shifts.

Interview Follow-Up Traps

Interviewer asks: "Can you wrap the root layout in a React Context provider?" Trap answer: No, Context is forbidden in App Router. Correct answer: Yes! You can wrap children in a Context provider, provided the provider file has \"use client\". Because Server Components can be passed as children, the server tree inside retains zero-bundle benefits.

Interviewer asks: "How do you pass initial server data to a Zustand store without hydration mismatch?" Trap answer: Fetch it in useEffect. Correct answer: Use a Zustand store creator with a React Context wrapper that initializes the store instance with server props during initial render.

Frequently Asked Questions

Why is React Context prohibited in Server Components?

Context relies on interactive subscription and reconciliation cycles, which do not exist in stateless, run-to-completion Server Components.

Redux is rarely needed for server data caching in modern Next.js, but remains useful for complex client-side workflows with extensive state interactions (e.g. rich canvas editors).

Use the useSearchParams() hook from next/navigation.

Access the searchParams prop passed to page.tsx (await searchParams in Next.js 15+).

Libraries like nuqs provide type-safe, URL-synchronized state hooks for Next.js.