DEV Community

Abhishek V
Abhishek V

Posted on

Zustand - React Global State Management Made Easy

Source code available on Github.

In this article

Introduction

In any React application, efficiently sharing state between components is crucial. While React's Context API is suitable for simple applications, complex ones demand a more robust solution. That's where Zustand comes into play. In React, we often turn to Redux for global state management, but Zustand offers a lightweight alternative. It leverages React Hooks API, boasts a small bundle size, and seamlessly integrates with TypeScript. In this article, we'll explore how to harness Zustand for global state management in React applications.

Why Zustand over Redux?

Before diving into Zustand, let's briefly consider why you might prefer it over Redux:

  • Lightweight: Zustand is a compact, fast, and scalable state management library.
  • Hooks-Based: It's built on top of React Hooks API, making it more intuitive for React developers.
  • Minimal Boilerplate: Zustand significantly reduces the amount of boilerplate code compared to Redux.
  • TypeScript-Friendly: It easily integrates with TypeScript, ensuring strong type checking.

In summary, Zustand presents a simple yet powerful alternative to Redux for handling global state in React applications.

Getting Started

To demonstrate how Zustand works, let's create a new React application. For this tutorial, we'll use Vite, but you can use any other tool of your choice. First, create a new project:



npm create vite-app zustand-react


Enter fullscreen mode Exit fullscreen mode

After generating the project, you can delete the unnecessary files, leaving you with the following folder structure:

Project Structure

Now, let's install Zustand:



npm install zustand


Enter fullscreen mode Exit fullscreen mode

To start the development server, run:



npm run dev


Enter fullscreen mode Exit fullscreen mode

Refactoring the App Component

In the initial code, the App component manages a counter using the useState hook. We will refactor this code to use Zustand for state management.



import React from "react";
import Counter from "./components/Counter";

function App() {
  return (
    <>
      <h1>Vite + React</h1>
      <Counter />
    </>
  );
}

export default App;


Enter fullscreen mode Exit fullscreen mode

In this refactored version, we've removed the count and setCount states from the App component, as we'll use Zustand to manage the state of the counter.

Creating Components

Now, let's create two components for our counter: Button and Counter.

Button Component



import React from "react";
import useCounter from "../store/counter";

const Button = ({ children, action }) => {
  const { increase, decrease } = useCounter();

  const handleClick = action === "increase" ? increase : decrease;

  return <button onClick={handleClick}>{children}</button>;
};

export default Button;


Enter fullscreen mode Exit fullscreen mode

In this updated Button component, we've removed the setCount prop and are instead using the increase and decrease functions from the useCounter hook.

Counter Component



import React from "react";
import Button from "./Button";
import useCounter from "../store/counter";

const Counter = () => {
  const { count } = useCounter();

  return (
    <>
      <div className="card">
        <Button action="increase">Increase</Button>
        <div>{count}</div>
        <Button action="decrease">Decrease</Button>
      </div>
    </>
  );
};

export default Counter;


Enter fullscreen mode Exit fullscreen mode

In the refactored Counter component, we've eliminated the need for count and setCount props by utilizing the count state from the useCounter hook.

Leveraging Zustand's Power

To showcase the full potential of Zustand, let's enhance our counter store.



// store/counter.js
import { create } from "zustand";

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

export default useCounter;


Enter fullscreen mode Exit fullscreen mode

Here, we've added increase and decrease functions to the store. These functions update the count state using the set function provided by Zustand.

Now, let's update the Button component to utilize these functions directly:



// components/Button.jsx
import React from "react";
import useCounter from "../store/counter";

const Button = ({ children, action }) => {
  const { increase, decrease } = useCounter();

  const handleClick = action === "increase" ? increase : decrease;

  return <button onClick={handleClick}>{children}</button>;
};

export default Button;


Enter fullscreen mode Exit fullscreen mode

By doing this, we've eliminated the need for the setCount prop in the Button component, showcasing Zustand's simplicity in state management.

Conclusion

In this article, we've explored how Zustand can be a lightweight yet robust alternative to Redux for global state management in React applications. By centralizing state management in a store and leveraging hooks, Zustand simplifies complex state management scenarios, reducing the need for prop drilling and boilerplate code.

To learn more about Zustand and its advanced features, refer to the official documentation and consider using it in your future React projects for efficient global state management.

Happy coding! 🚀

Top comments (0)