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.md
source 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

  1. Classify state — categorize every piece of state: local (component), global (Zustand), server (TanStack Query), URL (search params).
  2. Start local — use
    useState
    /
    useReducer
    first. Only lift to global when 3+ components need it.
  3. Set up Zustand — create store with
    create()
    . Use selectors to prevent unnecessary re-renders.
  4. Add TanStack Query
    useQuery({ queryKey, queryFn })
    for reads,
    useMutation
    for writes with
    onSuccess: () => queryClient.invalidateQueries()
    .
  5. Use URL state — put filters, pagination, and sort in URL params. Use
    useSearchParams()
    (React Router) or
    nuqs
    (Next.js).
  6. Combine patterns — Zustand for UI state (sidebar open, theme), TanStack Query for server data, URL for shareable state.
  7. Test — verify state updates trigger correct re-renders. Test Zustand stores independently of components.

State categories

CategoryToolExamples
Local
useState
Form inputs, toggle, hover
Server cacheTanStack QueryAPI data, paginated lists
Global clientZustandAuth user, theme, sidebar
URL
useSearchParams
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 —
    useStore(s => s.field)
    not
    useStore()
    to avoid full re-renders.
  • 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

  • react-typescript
    — typed state patterns
  • forms-validation
    — form-specific state
  • nextjs-app-router
    — server-side data fetching