Skip to content

Zustand for state management in React.js

Updated: at 09:57 AM

zustand-reactjs

State management becomes very crucial when it comes to build a robust React applications, and Zustand has emerged as a lightweight, elegant solution that simplifies the way we handle global state.

Table of contents

Open Table of contents

What is Zustand?

zustand-reactjs As said, Zustand is a small, fast and scalable status management solution. Its state management is centralized and action-based. Its core philosophy is to make state management straightforward and developer-friendly.

Advantages of using Zustand

Quick Installation

npm install zustand
# or
yarn add zustand

Once the library is installed, we need to create a folder /hooks and inside the folder we add a new file, I am creating use-cart.ts.

I am taking example of my ecommerce-store app where I have used zustand for state management.

Creating Store

Zustand provide function to create store using create and set variables to certain function using set that can be activated using certain conditions.

Importing zustand

import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";

Here, use-cart.ts basically handles the card activity for the ecommerce app. First step would be to set the variables

import { Product } from "@/types";
interface CartProps {
    items: Product[];
    addItem: (data: Product) => void;
    removeItem: (id: string) => void;
    removeAll: () => void;
};

Here, data is of type Product as in

export interface Product {
    id: string;
    name: string;
    price: string;
}

Now, we can create a store by using above variables and functions as

const useCart = create(
    // Store definition
    persist<CartProps>((set, get) => ({
        // Initial state
        items: [],

        // Method to add an item to the cart
        addItem: (data: Product) => {
            const currentItems = get().items;
            const existingItem = currentItems.find((item) => item.id === data.id);

            if(existingItem) {
                return toast("Item already in cart.")
            }

            set({ items: [...get().items, data] });
            toast.success("Item added to cart.")
        },

        // Method to remove a specific item from the cart
        removeItem: (id: string) => {
            set({ items: [...get().items.filter((item) => item.id !== id)] });
            toast.success("Item removed from the cart.");
        },

        // Method to clear all items from the cart
        removeAll: () => set({ items: [] }),
    }), 
    // Persistence configuration
    {
        name: "cart-storage",
        storage: createJSONStorage(() => localStorage)
    })
)
export default useCart;

Key Components

Zustand Store Creation:
create() is a Zustand method to create a global state store. persist() is a middleware that allows saving the store’s state to local storage. set and get are used to modify and retrieve the current state of the variables.

const useCart = create(
    persist<CartProps>((set, get) => ({
    }))
)

Store State:
items: An array to store cart items by starting as an empty array []

Methods:

addItem: (data: Product) => {
    const currentItems = get().items;
    ...
    set({ items: [...get().items, data] });
    ...
}

Here, current state of data is retrieved which of type Product using get. set is used to modify the state.

removeItem: (id: string) => {
    set({ items: [...get().items.filter((item) => item.id !== id)] });
    ...
}

Again, set is used to remove the item from cart i.e localStorage using the id of product

Persistence Configuration:

This is just an example, but the principle remain same.

Executing the action

It can be easily imported and be used for state management in other components.

We can create an object using the hook that we created earlier and subject the variables though it for overall state-management

import useCart from "@/hooks/use-cart";
// creating object 
const cart = useCart();

Now, it can be used in action to provide the parameters.

function ProductComponent() {
  const { addItem } = useCart();
  
  return (
    <button onClick={() => addItem(product)}>
      Add to Cart
    </button>
  );
}

function CartComponent() {
  const { items, removeItem, removeAll } = useCart();
  
  return (
    <div>
      {items.map(item => (
        <div key={item.id}>
          {item.name}
          <button onClick={() => removeItem(item.id)}>Remove</button>
        </div>
      ))}
      <button onClick={removeAll}>Clear Cart</button>
    </div>
  );
}

This implementation provides a robust, globally accessible cart state management solution with local storage persistence and user-friendly notifications.

Conclusion

Navigating the complexities of state management in React just got easier with Zustand. This innovative library cuts through the traditional complexity, offering developers an elegant and straightforward approach to handling global application states.

Thanks for joining me on this deep dive into Zustand. I hope this guide has demystified state management and shown you how powerful yet simple this library can be.


Next Post
Google OAuth Service