Intro
State management has always been a challenge for developers working in React. Maybe this is due, in part, to the fact that React is a “library”, not a “framework”. Over the years, we had a lot of great solutions like Redux, Flux, XState, …etc and each new one is better than the previous one! Today, we will learn a brand new state management library not just for React, but it can be used with any other framework.
What is Zustand
Zustand is a small, fast, and scalable bearbones state-management solution using simplified flux principles. It has a comfy API based on hooks, and isn't rigid or opinionated.
Learn Zustand under 30 seconds
First, create the store file, for example: useStore.js
:
import create from ‘zustand’;
const useStore = create(() => ({
name: 'Mark',
}));
Then, import that hook wherever you want.
This is how you get the state:
useStore(state => state.name)
And this is how you set it
useStore.setState({name: ‘John’})
Here is a live example, run npm run dev
:
Congratulations, you have the basics! 🎉
Ready to go deeper?
Add actions in the store
The previous example is oversimplified but we can use more advanced examples with actions instead of setting the state directly.
So, let’s create a new store for a counter:
import create from ‘zustand’;
const useStore = create(set => {
count: 0,
increment: () => set(state => ({count: state.count + 1})),
decrement: () => set(state => ({count: state.count + 1})),
})
As you see, we pass the set
prop in the function inside create
, and we can use it to set the state internally. Also, we can pass the state
prop in the set
function to access the current state in the store.
Here is a live example, run npm run dev
:
Use get()
in actions
But what if we need to access one of the current states inside a specific action without using set
? Well, there is the get
function, and its job is to just get a current state value.
const useStore = create((set, get) => ({
sound: "grunt",
action: () => {
const sound = get().sound
// ...
}
})
Async actions
You can use asynchronous actions because Zustand deals with actions as normal functions, so you can easily use an async function like this:
const useStore = create(set => ({
posts: {},
getPosts: async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts')
set({ posts: await response.json() })
}
}))
Use Zustand with vanilla javascript
Zustand can work outside of React with any JavaScript framework, or just with vanilla JavaScript, without any framework, by using 'zustand/vanilla':
import create from 'zustand/vanilla'
const store = create(() => ({ ... }))
You can then access the store content in other files like this:
const { getState, setState, subscribe, destroy } = store
Why Use Zustand Over Redux or React Context
- Easy to use
- Very small library
- Can be used with other frameworks or vanilla javascript
- Has better performance since it will inform components transiently (it doesn't force React to re-render the component because the state has changed)
- Allows developers to avoid over-engineering, especially in big projects