🐻 Bear necessities for state management in React
Zustand is a lightweight state management library for React that uses a hook-based API to manage application state with minimal boilerplate. Created as an alternative to Redux and Context API, it provides a simplified flux-like architecture where stores are hooks created with a single create function. The entire library has no external dependencies and weighs only a few kilobytes, making it one of the most performant state management solutions available.
The library eliminates the need for context providers, reducers, action types, or deeply nested wrapper components. Instead, you define state and actions in a single store function, and components subscribe to specific state slices automatically. Only components that use changed state slices will re-render, optimizing performance without manual optimization. This selective subscription model handles React's concurrent rendering features and avoids common pitfalls like the zombie child problem.
With over 20 million weekly downloads, Zustand has become a popular choice for teams building React applications of any scale. It supports middleware for persistence, logging, and Redux DevTools integration, works with both JavaScript and TypeScript, and can even manage state outside of React components. The library's unopinionated design means it doesn't enforce specific patterns, allowing developers to structure their state management according to their project's needs while maintaining simplicity.
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
interface TodoStore {
todos: Array<{ id: number; text: string; completed: boolean }>;
addTodo: (text: string) => void;
toggleTodo: (id: number) => void;
removeTodo: (id: number) => void;
}
const useTodoStore = create<TodoStore>()(persist(
(set) => ({
todos: [],
addTodo: (text) => set((state) => ({
todos: [...state.todos, { id: Date.now(), text, completed: false }]
})),
toggleTodo: (id) => set((state) => ({
todos: state.todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
})),
removeTodo: (id) => set((state) => ({
todos: state.todos.filter(todo => todo.id !== id)
}))
}),
{ name: 'todo-storage', storage: createJSONStorage(() => localStorage) }
));
function TodoList() {
const todos = useTodoStore((state) => state.todos);
const toggleTodo = useTodoStore((state) => state.toggleTodo);
const removeTodo = useTodoStore((state) => state.removeTodo);
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
{todo.text}
</span>
<button onClick={() => removeTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
);
}
function TodoInput() {
const addTodo = useTodoStore((state) => state.addTodo);
const [input, setInput] = React.useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (input.trim()) {
addTodo(input);
setInput('');
}
};
return (
<form onSubmit={handleSubmit}>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button type="submit">Add Todo</button>
</form>
);
}Global Application State: Managing user authentication, theme preferences, or shopping cart data that needs to be accessed across multiple components without prop drilling or context provider nesting.
Form State Management: Handling complex multi-step forms where state needs to be shared between wizard steps, with actions to validate, navigate, and persist form data across component unmounts.
Real-Time Data Updates: Managing WebSocket connections and live data feeds where multiple components need to subscribe to and display the same real-time information with minimal re-renders.
Client-Side Caching: Storing API responses and implementing cache invalidation strategies for data that's fetched frequently, reducing network requests and improving application responsiveness.
UI State Coordination: Managing modal visibility, sidebar toggles, notification queues, or loading states that affect multiple parts of the application simultaneously without passing callbacks through component trees.
👻 Primitive and flexible state management for React
Simple, scalable state management.
Recoil - A state management library for React
Predictable state container for JavaScript apps
🧙 Valtio makes proxy-state simple for React and Vanilla
npm install zustandpnpm add zustandbun add zustand