
Day 22 – Zustand in React
In this blog, we’ll cover Zustand in React, step by step, with examples and a comparison with Redux Toolkit.
In the previous blog (Day 21), we explored Redux Toolkit in React — a powerful, scalable state management solution. But Redux Toolkit can still feel heavy for small to medium apps.
That’s where Zustand comes in — a lightweight, simple, and modern state management library for React. It requires minimal setup, no boilerplate, and works perfectly with React hooks.
Why Zustand?
Here’s why developers are switching to Zustand for smaller projects:
- Minimal boilerplate → No slices, actions, or reducers.
- Direct state mutation → Update state directly without Immer.
- Built for hooks → Works seamlessly with React hooks.
- Easy to learn → Simple API, almost no concepts to memorize.
- Flexible & scalable → Can grow with your app.
Step 1: Install Zustand
npm install zustand
Step 2: Create a Store
Zustand stores are simple functions. Let’s create a counter store in counterStore.js
:
import { create } from "zustand";
const useCounterStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
incrementByAmount: (amount) => set((state) => ({ count: state.count + amount })),
}));
export default useCounterStore;
👉 Key points:
create
defines a store hook (useCounterStore
).set
updates state directly.- No separate action types or reducers are needed.
Step 3: Use Zustand in Components
In App.js
:
import React from "react";
import useCounterStore from "./counterStore";
function App() {
const { count, increment, decrement, incrementByAmount } = useCounterStore();
return (
<div style={{ textAlign: "center", marginTop: "50px" }}>
<h1>Zustand Counter</h1>
<h2>{count}</h2>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={() => incrementByAmount(5)}>Increment by 5</button>
</div>
);
}
export default App;
👉 Notice how clean and simple this is compared to Redux Toolkit. No Provider, no useDispatch, no useSelector. Just hooks.
Zustand Flow
Here’s the flow of Zustand:
- Component calls a store hook (
useCounterStore
). - Store returns state + actions.
- Component triggers an action (e.g.,
increment()
). - Zustand updates the state directly, and subscribed components re-render automatically.
Real-World Example: Authentication State
Zustand can manage auth state just as easily:
const useAuthStore = create((set) => ({
isLoggedIn: false,
login: () => set({ isLoggedIn: true }),
logout: () => set({ isLoggedIn: false }),
}));
export default useAuthStore;
In components:
const { isLoggedIn, login, logout } = useAuthStore();
<button onClick={login}>Login</button>
<button onClick={logout}>Logout</button>
{isLoggedIn && <p>Welcome, user!</p>}
✅ Much cleaner than Redux Toolkit, especially for small apps.
Redux Toolkit vs Zustand
Feature | Redux Toolkit | Zustand |
---|---|---|
Boilerplate | Medium | Very Low |
Learning Curve | Moderate | Easy |
DevTools | Built-in | Optional |
State Mutability | Immer-powered (can mutate state) | Direct state mutation |
Async Handling | Thunks / Middleware | Built-in or middleware optional |
Suitable for | Large projects | Small to medium projects, lightweight state |
👉 Use this table as a quick decision guide for your project.
Conclusion
In this blog, we learned Zustand in React:
- Minimal setup for state management.
- No boilerplate, direct state updates.
- How to create a store, use it in components, and handle actions.
- Real-world example: Authentication state.
- Quick comparison with Redux Toolkit.
In the next blog (Day 23), we will create a “Mini Blog Project in React” that ties together everything the series has taught so far — hooks, state management, routing, API calls, forms, and UI components.