Written by: ekwoster.dev on Tue Aug 12

State Management Made Simple with Zustand: A Modern Alternative to Redux

State Management Made Simple with Zustand: A Modern Alternative to Redux

Cover image for State Management Made Simple with Zustand: A Modern Alternative to Redux

State Management Made Simple with Zustand: A Modern Alternative to Redux

Managing state in modern React applications can get complicated fast. Redux, Context API, MobX—developers have many tools available, but many of them come with significant boilerplate, complexity, or performance issues. If you're looking for a lightweight and intuitive approach to state management, then look no further than Zustand.

In this blog post, we'll explore what makes Zustand a compelling choice, how to get started with it, and dive into practical examples and patterns to make your React state handling a breeze.

What Is Zustand?

Zustand (pronounced "zoo-shtand", meaning "state" in German) is a small, fast, and scalable state management solution for React apps built by the developers at Poimandres—the same team behind popular libraries like React Three Fiber and Jotai.

At its core, Zustand uses hooks to create and interact with a state store. It simplifies state management dramatically compared to Redux or other more elaborate systems.

Why Use Zustand Over Redux or Context API?

Here are a few standout reasons:

  • 🪶 Minimal boilerplate: Zustand uses native hooks internally and needs very little setup.
  • ⚡ Performance: Selective listening means components only re-render when relevant parts of the state change.
  • 🔍 Debuggable: Zustand integrates seamlessly with Redux DevTools.
  • 🧠 Simple mental model: No actions, reducers, or middlewares unless you really want them.
  • ⛓️ No Provider required: Because Zustand stores are just hooks, you don’t need to wrap your app in a context provider.

Getting Started

Let’s walk through setting up Zustand in a simple React app.

Install Zustand

npm install zustand

Or with yarn:

yarn add zustand

Define Your Store

Create a file useStore.js:

import { create } from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increase: () => set((state) => ({ count: state.count + 1 })),
  decrease: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}));

export default useStore;

Use Your Store in a Component

import React from 'react';
import useStore from './useStore';

export default function Counter() {
  const { count, increase, decrease, reset } = useStore();

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increase}>+</button>
      <button onClick={decrease}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

That’s it. No reducers, dispatchers, or context wrappers. Zustand brings clarity and focus to your state handling.

Selective State Access

Care about performance? Zustand allows you to subscribe only to the pieces of state you need:

const count = useStore((state) => state.count);

This way, the component only re-renders when count changes, not when other parts of the store do.

Middleware and Persistence

Zustand supports middleware too, such as for logging, persistence, or Redux DevTools integration.

Example: Persist Your Store

import { create } from 'zustand';
import { persist } from 'zustand/middleware';

const useStore = create(persist(
  (set) => ({
    count: 0,
    increase: () => set((state) => ({ count: state.count + 1 })),
  }),
  {
    name: 'counter-storage',
  }
));

This example automatically saves and restores the store from localStorage.

Zustand vs Redux: A Quick Comparison

FeatureZustandRedux
BoilerplateMinimalHigh
Built-in DevToolsYes (via middleware)Yes
Built-in PersistenceYesNo (requires extra lib)
Learning CurveLowMedium/High
Middleware SupportYesYes
Context Provider NeededNoYes

Composing Stores

Need to split state into modules as your app grows? Zustand supports multiple stores or composable state slices.

Example: Auth Slice + UI Slice

// authStore.js
export const createAuthSlice = (set) => ({
  user: null,
  login: (user) => set({ user }),
  logout: () => set({ user: null }),
});

// uiStore.js
export const createUISlice = (set) => ({
  darkMode: false,
  toggleDarkMode: () => set((state) => ({ darkMode: !state.darkMode })),
});

// store.js
import { create } from 'zustand';
import { createAuthSlice } from './authStore';
import { createUISlice } from './uiStore';

const useStore = create((set) => ({
  ...createAuthSlice(set),
  ...createUISlice(set),
}));

export default useStore;

When Not to Use Zustand?

While Zustand is excellent for most use cases, it may not be ideal when:

  • You’re deeply integrated into the Redux ecosystem.
  • Team familiarity with Redux is high.
  • You require complex middleware chaining or time-travel debugging out-of-the-box.

However, for new projects or developers tired of Redux’s verbosity, Zustand is a breath of fresh air.

Real-World Use Case: Global Notifications

Here’s a common use case for shared state—having a global toast notification system:

// notificationStore.js
import { create } from 'zustand';

const useNotificationStore = create((set) => ({
  message: '',
  type: '',
  notify: ({ message, type }) => set({ message, type }),
  clear: () => set({ message: '', type: '' }),
}));

export default useNotificationStore;

Then in your Notification component:

const Notification = () => {
  const { message, type, clear } = useNotificationStore();

  useEffect(() => {
    if (message) {
      const timeout = setTimeout(clear, 3000);
      return () => clearTimeout(timeout);
    }
  }, [message]);

  if (!message) return null;

  return <div className={`toast toast-${type}`}>{message}</div>;
};

Triggering a notification anywhere in the app is now easy:

useNotificationStore.getState().notify({ message: 'Profile saved!', type: 'success' });

Conclusion

If you’re building modern React apps and want to simplify state management, Zustand is a highly performant and developer-friendly alternative to Redux or Context API. With its intuitive API, composability, and support for middleware, it covers most use cases with minimal overhead.

As React evolves, state management tools should too—Zustand reflects that future with grace and efficiency.

Give Zustand a try in your next project—it might just become your new favorite state manager.

Resources

Happy coding! 🚀

💡 If you're looking for expert help with building modern frontend solutions using tools like Zustand – we offer such services.