nextjs-state-management
$
npx mdskill add HoangNguyen0403/agent-skills-standard/nextjs-state-management1. **Shareable/persistent?** Use URL state (`useSearchParams` + `useRouter`). 2. **Server data?** Use SWR or TanStack Query. Never sync into `useState`. 3. **Complex client UI?** Use Zustand (in `'use client'` only) or Jotai. 4. **Simple local?** Use `useState`. Colocate as close to consumer as possible.
SKILL.md
.github/skills/nextjs-state-managementView on GitHub ↗
---
name: nextjs-state-management
description: Apply best practices for managing URL, server, and client state in Next.js applications. Use when choosing between URL params, SWR/TanStack Query, Zustand, or Context for state, or when fixing hydration mismatches from localStorage.
metadata:
triggers:
files:
- '**/hooks/*.ts'
- '**/store.ts'
- '**/components/*.tsx'
keywords:
- useState
- useContext
- zustand
- redux
---
# State Management
## **Priority: P2 (MEDIUM)**
## Decision Guide
1. **Shareable/persistent?** Use URL state (`useSearchParams` + `useRouter`).
2. **Server data?** Use SWR or TanStack Query. Never sync into `useState`.
3. **Complex client UI?** Use Zustand (in `'use client'` only) or Jotai.
4. **Simple local?** Use `useState`. Colocate as close to consumer as possible.
## URL-Driven State
See [implementation examples](references/implementation.md)
## Server State (SWR / TanStack Query)
See [implementation examples](references/implementation.md)
## Client State (Zustand)
See [implementation examples](references/implementation.md)
## Hydration Safety
Wrap `localStorage` reads in `useEffect` or `mounted` flag to avoid hydration mismatches. Manage optimistic updates with `useOptimistic` in Next.js 15+.
## Legacy Redux (existing projects)
If project already uses `redux@4` + `createStore` + `redux-thunk` + `next-redux-wrapper`:
- Use `useSelector` / `useDispatch` hooks — never connect HOC.
- Define typed `RootState` and typed `AppDispatch` for all selectors and dispatch calls.
- Avoid adding Zustand or TanStack Query on top of existing Redux codebase — migrate incrementally if needed.
- Migration path: Redux Toolkit (`@reduxjs/toolkit`) → RTK Query → then consider TanStack Query.
See [references/redux.md](references/redux.md) for typed selector and thunk patterns.
## Library Patterns
- [references/redux.md](references/redux.md)
- [references/zustand.md](references/zustand.md)
- [references/url-state.md](references/url-state.md)
## Anti-Patterns
- **No global store for simple state**: Use `useState` or URL params; avoid Zustand for basic UI.
- **No large objects in state**: Decompose into granular primitives to prevent extra re-renders.
- **No `useEffect` for data fetching**: Use SWR or TanStack Query for server state.
- **No server state in client stores**: Fetch in RSCs; client stores for UI-only state.