React

A Simple Guide to State Management in React with Zustand

Discover Zustand, a small, fast, and scalable state management solution for React. Learn how to simplify your app's state with minimal boilerplate.

July 25, 2025
4 min read
By useLines Team
ReactState ManagementZustandJavaScriptFrontend
Illustration for A Simple Guide to State Management in React with Zustand

What is Zustand?

Zustand is a small, fast, and scalable state management library for React. It's built on a minimalistic API that's easy to learn and use, and it leverages React hooks to provide a simple way to manage your application's state without the boilerplate of more complex solutions like Redux.

The name "Zustand" is German for "state," which perfectly captures its purpose. It's designed to be unopinionated and gives you the freedom to organize your state as you see fit.

Why Choose Zustand?

  • Minimal Boilerplate: Get up and running with just a few lines of code. No need for actions, reducers, or dispatchers for simple state changes.
  • Hook-Based API: If you know React Hooks, you'll feel right at home with Zustand.
  • Performance: Zustand only re-renders components when the state they subscribe to changes, leading to better performance.
  • Small Bundle Size: It's a lightweight library that won't add much to your application's bundle size.

Getting Started with Zustand

First, you need to add Zustand to your project:

npm install zustand

Creating a Store

A "store" in Zustand is a hook that holds your state and the functions to update it. Here's how to create a simple store to manage a counter:

import { create } from 'zustand';

const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));

export default useCounterStore;

In this example, create is the core function from Zustand. It takes a function that receives a set callback. This set function is used to update the state.

Using the Store in a Component

Now, you can use your new useCounterStore hook in any React component to access and update the state.

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

function Counter() {
  const { count, increment, decrement } = useCounterStore();

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

export default Counter;

That's it! Your Counter component is now connected to the Zustand store. When you call increment or decrement, the state will update, and the component will re-render to display the new count.

Advanced Usage

Async Actions

Zustand makes it easy to handle asynchronous operations, like fetching data from an API.

import { create } from 'zustand';

const useUserStore = create((set) => ({
  user: null,
  loading: false,
  fetchUser: async (userId) => {
    set({ loading: true });
    try {
      const response = await fetch(`https://api.example.com/users/${userId}`);
      const user = await response.json();
      set({ user, loading: false });
    } catch (error) {
      set({ loading: false });
      console.error('Failed to fetch user', error);
    }
  },
}));

Slices Pattern

For more complex state, you can split your store into "slices," which is a common pattern for better organization.

const createCounterSlice = (set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
});

const createThemeSlice = (set) => ({
  theme: 'light',
  toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })),
});

const useBoundStore = create((...a) => ({
  ...createCounterSlice(...a),
  ...createThemeSlice(...a),
}));

By adopting Zustand, you can simplify your state management logic, reduce boilerplate, and improve the performance of your React applications. It's a powerful tool that scales with your project's needs.

Related Posts