State Management¶
State Management¶
Local State First¶
Always start with local state. Only lift state when necessary:
// Start here - local state
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
// Lift only when siblings need the state
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<Counter count={count} onChange={setCount} />
<Display count={count} />
</>
);
}
TanStack Query for Server State¶
Use TanStack Query for all server data:
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
// Query keys - consistent structure
const userKeys = {
all: ['users'] as const,
lists: () => [...userKeys.all, 'list'] as const,
list: (filters: UserFilters) => [...userKeys.lists(), filters] as const,
details: () => [...userKeys.all, 'detail'] as const,
detail: (id: string) => [...userKeys.details(), id] as const,
};
// Fetching data
function useUser(id: string) {
return useQuery({
queryKey: userKeys.detail(id),
queryFn: () => api.users.get(id),
staleTime: 5 * 60 * 1000, // 5 minutes
});
}
// Mutating data
function useUpdateUser() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: UserUpdate) => api.users.update(data),
onSuccess: (user) => {
queryClient.setQueryData(userKeys.detail(user.id), user);
queryClient.invalidateQueries({ queryKey: userKeys.lists() });
},
});
}
Zustand for Client State¶
Use Zustand for complex client-side state:
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
interface UIState {
sidebarOpen: boolean;
theme: 'light' | 'dark';
toggleSidebar: () => void;
setTheme: (theme: 'light' | 'dark') => void;
}
export const useUIStore = create<UIState>()(
persist(
(set) => ({
sidebarOpen: true,
theme: 'light',
toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),
setTheme: (theme) => set({ theme }),
}),
{ name: 'ui-storage' }
)
);
// Usage
function Sidebar() {
const { sidebarOpen, toggleSidebar } = useUIStore();
// ...
}
See Also¶
- Form Handling -- Managing form state with react-hook-form and Zod
- Providers -- React context providers for shared application state