Skilllibrary state-management
install
source · Clone the upstream repo
git clone https://github.com/merceralex397-collab/skilllibrary
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/merceralex397-collab/skilllibrary "$T" && mkdir -p ~/.claude/skills && cp -r "$T/08-web-frontend-and-design/state-management" ~/.claude/skills/merceralex397-collab-skilllibrary-state-management && rm -rf "$T"
manifest:
08-web-frontend-and-design/state-management/SKILL.mdsource content
Purpose
Manage React application state using Zustand for client state, TanStack Query for server cache, and URL state for shareable UI state.
When to use this skill
- choosing between local, global, server, and URL state
- setting up Zustand stores with slices and selectors
- integrating TanStack Query for data fetching and caching
- moving filter/sort/pagination state to URL params
Do not use this skill when
- building forms with validation — prefer
forms-validation - doing Next.js Server Component data fetching — prefer
nextjs-app-router - the task is component typing — prefer
react-typescript
Procedure
- Classify state — categorize every piece of state: local (component), global (Zustand), server (TanStack Query), URL (search params).
- Start local — use
/useState
first. Only lift to global when 3+ components need it.useReducer - Set up Zustand — create store with
. Use selectors to prevent unnecessary re-renders.create() - Add TanStack Query —
for reads,useQuery({ queryKey, queryFn })
for writes withuseMutation
.onSuccess: () => queryClient.invalidateQueries() - Use URL state — put filters, pagination, and sort in URL params. Use
(React Router) oruseSearchParams()
(Next.js).nuqs - Combine patterns — Zustand for UI state (sidebar open, theme), TanStack Query for server data, URL for shareable state.
- Test — verify state updates trigger correct re-renders. Test Zustand stores independently of components.
State categories
| Category | Tool | Examples |
|---|---|---|
| Local | | Form inputs, toggle, hover |
| Server cache | TanStack Query | API data, paginated lists |
| Global client | Zustand | Auth user, theme, sidebar |
| URL | | Filters, sort, page number |
Zustand store
import { create } from 'zustand'; type AuthStore = { user: User | null; setUser: (user: User | null) => void; logout: () => void; }; const useAuthStore = create<AuthStore>((set) => ({ user: null, setUser: (user) => set({ user }), logout: () => set({ user: null }), })); // Selector — only re-renders when user changes const user = useAuthStore((s) => s.user);
TanStack Query
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; function usePosts() { return useQuery({ queryKey: ['posts'], queryFn: () => api.getPosts() }); } function useCreatePost() { const qc = useQueryClient(); return useMutation({ mutationFn: (data: NewPost) => api.createPost(data), onSuccess: () => qc.invalidateQueries({ queryKey: ['posts'] }), }); }
Decision rules
- Default to local — most state belongs in the component that uses it.
- Server data is not global state — use TanStack Query, not Zustand, for API responses.
- Use Zustand selectors —
notuseStore(s => s.field)
to avoid full re-renders.useStore() - URL state for anything a user might bookmark or share — filters, tabs, pagination.
- Never duplicate server data in Zustand — TanStack Query is the cache; Zustand is for UI state.
References
Related skills
— typed state patternsreact-typescript
— form-specific stateforms-validation
— server-side data fetchingnextjs-app-router