In this post we are going to look closely to one of the state management libraries - Zustand.
This is a good alternative to Redux for development of React applications if you find Redux too complicated or too heavy for your current project.
What is Zustand?
Zustand (a german word that means 'state' in English) - a state-management library. In official documentation they call it "a small, fast and scalable bearbones state-management solution".
It helps to solve such problems as "zombie child" problem, React concurrency and context loss between mixed renderers.
If you want to read about those issues more detailed, here are the links:
- React concurency - https://github.com/bvaughn/rfcs/blob/useMutableSource/text/0000-use-mutable-source.md.
- context loss - https://github.com/facebook/react/issues/13332 AND the most beauty of it is that the store it provides is a hook and you can put objects or functions in it. How awesome is that!
How to use Zustand?
Below you will find the step-by step guide about how to use Zustand in your React project.
Before you follow the steps, make sure that you can created a react project either with CRA or Vite and it is up and running.
Step 1 - Import
This library can be imported to your project very easy with npm or yarn:
npm install zustand
yard add zustand
Step 2 - Create Store
Zustand gives us possibility to use the state in any component in our application. In order to do that, we need to create a store for the state.
We will be using a simple To-Do app as an example here.
In the project files we create a folder which we call 'store' and in this folder we create a file with the name 'useToDoStore.ts'
.
Remember, that Zustand store is a hook so it has to be named with 'use' at the beginning (rule of custom hooks)
Inside 'useToDoStore.ts'
file we create first an interface for our to-do task:
interface ToDo {
id: string;
title: string;
}
After that we create an interface for our ToDoStore, which will include an array of ToDos and methods to create, update and delete ToDos:
interface ToDoStore {
toDos: Todo[];
createToDo: (title: string) => void;
updateToDo: (id: string, title: string) => void;
deleteToDo: (id: string) => void;
}
Now we can continue and create actually a store. To do this, we need to import a specific method create
from the Zustand library and than use this method to create a store:
import create from "zustand";
export const useToDoStore = create<ToDoStore>((set, get) => ({
todos: [], // our array of todos is empty but
// it could be predefined as well
createToDo: (title) => {},
updateToDo: (id, title) => {},
deleteToDo: (id) => {},
}));
Method create
give us access to 2 important functions:
- set() - this function update the current state
- get() - this function gives access to the current state to outside Those functions work the same way as setters and getters in the class. We will use them when defining our store functions for ToDos.
Step 3 - Create Functions
Here we will use set()
and get()
functions from create
to define what our store functions will do.
Let's start from the function which creates todos:
createToDo: (title) => {
const { todos } = get(); // first we get all todos
const newTodo = {
id: generateId(),// helper function to create ID
title,
};
set({
todos: [...todos, newTodo]
});
},
}
Than we create a function which updates todos:
updateToDo: (id: string, title: string) => {
const { todos } = get();
set({
todos: todos.map(todo =>({
...todo,
title: todo.id === id? title : todo.id
}))
})
}
And the function which deletes todo:
deleteToDo: (id: string) => {
const { todos } = get();
set({
todos: todos.filter(todo => todo.id !== id)
})
},
Congratulations, we have a store now :) Lets use it!
Step 4 - Use Store
To use a store, go to the file with a component (for example ToDoList.tsx), import the ToDoStore and destructure the state and/or necessary methods from the hook. You can use all methods or just specific method in any component:
const [todos, createToDo, updateToDo, deleteToDo] = useToDoStore((state) => [
state.todos,
state.createToDo,
state.updateToDo,
state.deleteToDo,
]);
Now your state can be used in the file of specific component where you need it to be used. Use the hook anywhere without any providers.
Conclusion
- this library is small and easy to use
- renders components only on change
- no context providers needed
- can be used without React
If you want to learn more about Zustand and what is proposes, visit the official page at https://github.com/pmndrs/zustand
Top comments (1)
Very Insightful!