Introduction
State management is crucial for any React application, but traditional libraries like Redux can sometimes feel like overkill. Enter Zustand, a minimal and powerful state management solution for React. In this post, we’ll dive into why Zustand is becoming a favorite for developers and how to get started with it in your React projects.
What is Zustand?
Zustand is a state management library for React that is designed to be simple and intuitive. It is lightweight and doesn't require a lot of boilerplate, which makes it easier to use than Redux or even the React Context API. Let's take a look at how we can use Zustand in our React applications.
Setting Up Zustand in React
-
Install Zustand
npm install zustand
-
Create a Store
Here's a simple example of how to create a store in Zustand:
import {create} from 'zustand'; const useStore = create((set) => ({ count: 0, increase: () => set((state) => ({ count: state.count + 1 })), decrease: () => set((state) => ({ count: state.count - 1 })), }));
-
Using the Store in a Component
Now, let's use the store in a React component:
import React from 'react'; import { useStore } from './store'; const Counter = () => { const { count, increase, decrease } = useStore(); return ( <div> <h1>{count}</h1> <button onClick={increase}>Increase</button> <button onClick={decrease}>Decrease</button> </div> ); }; export default Counter;
Advanced Zustand Features: get, getState
- Zustand also provides two other useful functions: get and getState. These are used to retrieve the state and get the state at any point in time
getState(): This function gives you the current state of the store without triggering a re-render.
import {create} from 'zustand';
const useStore = create((set) => ({
count: 0,
increase: () => set((state) => ({ count: state.count + 1 })),
decrease: () => set((state) => ({ count: state.count - 1 })),
}));
// Accessing the current state using getState()
const count= useStore.getState().count;
// Reading the current state value
console.log(count); // This will log the current count
// Modifying the state using the actions
store.increase(); // This will increase the count
console.log(store.count); // This will log the updated count
get(): This function allows you to directly access state from within the store itself. It’s useful if you need to check or modify state before or after setting it.
import {create} from 'zustand';
const useStore = create((set, get) => ({
count: 0,
increase: (amount) => {
const currentState = get(); // Access the current state using getState()
console.log("Current count:", currentState.count); // Log the current count
set((state) => ({ count: state.count + amount })); // Modify the state
},
}));
Slices in Zustand
- As your application grows, it’s a good idea to organize your state into smaller, more manageable pieces. This is where slices come into play. A slice is a modular piece of state with its own set of actions. Each slice can be defined in its own file, making your code cleaner and more maintainable.
// counterStore.js
export const createCounterSlice = (set) => ({
count: 0,
increase: () => set((state) => ({ count: state.count + 1 })),
decrease: () => set((state) => ({ count: state.count - 1 })),
});
// userStore.js
export const createUserSlice = (set) => ({
user: { name: 'John Doe' },
setName: (name) => set({ user: { name } }),
});
// useBoundStore.js
import {create} from 'zustand';
import { createCounterSlice } from './counterStore';
import { createUserSlice } from './userStore';
export const useBoundStore = create((...a) => ({
...createCounterSlice(...a),
...createUserSlice(...a),
}));
How to use inside component
import { useBoundStore } from './useBoundStore'
const App = () => {
const { count, increase, decrease, user, setName } = useBoundStore();
}
Persisting State in Zustand
- Zustand's persist middleware automatically saves the state to localStorage when it changes and loads it back when the page is reloaded, making sure the state stays the same without needing extra work.
import {create} from 'zustand';
import { persist } from 'zustand/middleware';
const useStore = create(
persist(
(set) => ({
count: 0,
increase: () => set((state) => ({ count: state.count + 1 })),
decrease: () => set((state) => ({ count: state.count - 1 })),
}),
{
name: 'counter-storage', // The name of the key in localStorage
}
)
);
Fetching Data from an API in Zustand
- To fetch data from an API in Zustand, create an action within your store to handle the API call and update the state with the fetched data, loading, and error states.
import {create} from 'zustand';
const useStore = create((set) => ({
users: [], // Array to store fetched users
loading: false, // State to track loading status
error: null, // State to track any errors during API call
// Action to fetch users from the API
fetchUsers: async () => {
set({ loading: true, error: null }); // Set loading state to true and reset error
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const data = await response.json();
set({ users: data, loading: false }); // Set users data and loading to false
} catch (error) {
set({ error: 'Failed to fetch users', loading: false }); // Set error if fetch fails
}
},
}));
export default useStore;
Top comments (0)