How to use Zustand for State Management for API CRUD

Use Zustand for state management and making API calls (both GET and update operations) in a React functional component.

1. Installation and Setup:

First, install the zustand library in your project:


npm install zustand

2. Creating a Store:

Create a store.js file and add all required method for call API.

// 
import create from 'zustand';

const useStore = create((set) => ({
  data: null,
  error: null,
  fetchData: async (url) => {
    try {
      const response = await fetch(url);
      const data = await response.json();
      set({ data, error: null });
    } catch (error) {
      set({ data: null, error: error.message });
    }
  },
  updateData: async (url, newData) => {
    try {
      const response = await fetch(url, {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(newData),
      });
      const updatedData = await response.json();
      set({ data: updatedData, error: null });
    } catch (error) {
      set({ error: error.message });
    }
  },
}));

export default useStore;
//

3. Using the Store in a Component

In your functional component, import and use the useStore hook to access the state and methods from the store:

//
import React, { useEffect } from 'react';
import useStore from './store';

const App = () => {
  const { data, error, fetchData, updateData } = useStore();

  useEffect(() => {
    fetchData('https://api.example.com/data');
  }, []);

  const handleUpdate = () => {
    const newData = { /* Updated data */ };
    updateData('https://api.example.com/update', newData);
  };

  return (
    < div >
      {data && < pre >{JSON.stringify(data, null, 2)}< /pre >}
      {error && < p >Error: {error}< /p >}
      < button onClick={handleUpdate} >Update Data< /button >
    < /div >
  );
};

export default App;
//

You can also use with typescript.

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

export interface IGetData {
  data: { name: string; code: string; fullName: string } | null;
  error: null;
  getData: (url: string) => void;
  geDatatById: (url: string, id: number) => void;
}

const useStore = create<IGetData>()(
  devtools(
    persist(
      (set) => ({
        data: null,

        error: null,

        getData: async (url: string) => {
          try {
            const response = await fetch(url);
            const data = await response.json();
            set({ data, error: null });
          } catch (error: any) {
            set({ data: null, error: error.message });
          }
        },
        geDatatById: async (url: string, id: number) => {
          try {
            const response = await fetch(`${url}/${id}`);
            const updatedData = await response.json();
            set({ data: updatedData, error: null });
          } catch (error: any) {
            set({ error: error.message });
          }
        },
      }),
      {
        name: "get-data",
      }
    )
  )
);

export default useStore;
 
//

In this example, we’ve created a zustand store that contains the state (data and error) along with methods (fetchData and updateData) for making API calls. The useEffect hook is used to trigger the initial API call when the component mounts. The handleUpdate function is used to trigger the update API call. Remember to replace the API URLs with the actual endpoints you want to use.

https://www.npmjs.com/package/zustand