#1 Data Analytics Program in India
₹2,499₹1,499Enroll Now
11 min read
•Question 47 of 47hard

State Management Patterns in Next.js

Managing state with Server and Client Components.

State Management

URL State

code.txtTSX
// Use URL for shareable state
'use client';

import { useSearchParams, useRouter } from 'next/navigation';

export function Filters() {
  const searchParams = useSearchParams();
  const router = useRouter();

  const updateFilter = (key: string, value: string) => {
    const params = new URLSearchParams(searchParams);
    params.set(key, value);
    router.push(`?${params.toString()}`);
  };

  return (
    <select onChange={(e) => updateFilter('sort', e.target.value)}>
      <option value="newest">Newest</option>
      <option value="popular">Popular</option>
    </select>
  );
}

Context for Client State

code.txtTSX
// providers/cart-provider.tsx
'use client';

const CartContext = createContext<CartContextType | null>(null);

export function CartProvider({ children }: { children: React.ReactNode }) {
  const [items, setItems] = useState<CartItem[]>([]);

  const addItem = (item: CartItem) => {
    setItems((prev) => [...prev, item]);
  };

  return (
    <CartContext.Provider value={{ items, addItem }}>
      {children}
    </CartContext.Provider>
  );
}

// In root layout
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <CartProvider>{children}</CartProvider>
      </body>
    </html>
  );
}

Zustand with Next.js

code.txtTSX
// stores/cart-store.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

interface CartStore {
  items: CartItem[];
  addItem: (item: CartItem) => void;
  removeItem: (id: string) => void;
}

export const useCartStore = create<CartStore>()(
  persist(
    (set) => ({
      items: [],
      addItem: (item) => set((state) => ({
        items: [...state.items, item]
      })),
      removeItem: (id) => set((state) => ({
        items: state.items.filter((i) => i.id !== id),
      })),
    }),
    { name: 'cart-storage' }
  )
);

// Hydration wrapper for SSR
'use client';

export function CartHydration() {
  const [hydrated, setHydrated] = useState(false);

  useEffect(() => {
    setHydrated(true);
  }, []);

  if (!hydrated) return null;
  return <Cart />;
}