DEV Community

cmphill
cmphill

Posted on

Zustand State Management

Introduction

Have you ever been frustrated by endless prop drilling, but were intimidated by state management solutions like Redux? Not to worry--there is a lightweight, low syntax, unopinionated solution called Zustand. Zustand allows you to create a file, called a store, that saves as many states as you like all in one file and import them in the components that you need them in. One of the great advantages of this approach is that Zustand supports variables of both primitive data types and of functions and arrays. The variables need not be related to one another in any form; you can place them all in the same store without any particular order. Furthermore, you can selectively import the variables that you need for a component instead of a wholesale import.

Getting started

The first thing you need to do to is install Zustand for your repository by running
npm install zustand
phew. Now that we have that out of the way, we'll begin the similarly strenuous process of creating the store. In a new file, (you can name this whatever you like, but store.js(x) is convention),

write import {create} from 'zustand'.
Your store is created, and now you can define variables.

Creating variables

There are several approaches to managing your store, including setting up a store and then adding on states and variables later. However, I found that having one large set with all the variables I needed worked just fine for a small project.

const useStore = create( set => ({
    users: [],
    addUser: (user) => set(state => ({users: 
    [...state.users, user]
    current_user: {},
    setCurrentUser: (state) => set({current_user: state}),
    logoutCurrentUser: () => set({current_user: 
    null}),
    items: [],
    addItems: (item) => set(state => ({items: [...state.items, item})),
    clearItems: () => set({items: []})
}))
 }))

export default useStore
Enter fullscreen mode Exit fullscreen mode

Importing and Using Variables

Once you have your variables created, you can import them into the component(s) they are needed for. If you are only including one or two variables, you can import them using the following syntax:

in your component:
//Example.jsx component
import useStore from "../store" //=> This will be whatever the relative path to your store component is

function Example() {
   const current_user = useStore((state) => state.current_user)
const setCurrentUser = useStore((state) => state.setCurrentUser)

   function setUser() {
    fetch("/api/login")
    .then((res) => res.json())
    .then((user) => {
    setCurrentUser({
     id: user.id,
     username: user.username,
    })
  }
}


Enter fullscreen mode Exit fullscreen mode

This simple implementation of store worked just fine for my small project. I used useEffect and the promise-based nature of fetches to manage asynchronous operations. However, Zustand is capable of handling async and it allows you to bundle variables together to re-render when the value of one changes.

One of the things you will want to do frequently once you have updated the state is to read it, of course. When you simply need the value of the state to render text in a DOM element, for example, you can assign it to a variable using the built in method on the store:
const user = useStore.getState.user. In this way you can access the value without updating it whenever you need to.

For example, you could write a store in this fashion:

const marbleStore = create((set) => ({
    marbles: {},
    fetch: async(marbleBag) => {
    const response = await fetch(marbleBag)
    set({marbles: await response.json()})
}
}))
Enter fullscreen mode Exit fullscreen mode

There are many such applications, including updating the re-rendering the component whenever one of the specified states from within the component changes.

Summary of Zustand Benefits

There are many advantages that make Zustand a great choice for a variety of projects. One is that it uses the logic of React hooks and (depending on how you use it, context). Doing so means that you don't have to write a lot of extra code to get started, and the library is quite small (less than 2kB, so it won't weigh down your repository). Because it is simple, it allows you to enter the world of state management without too much hassle. Another nice feature is the documentation. It provides many practical examples of the code in use as well as links to a sandbox where you can test out variations. Zustand automatically determines which which state a component needs and subscribes it, so no developer input is necessary in simple cases. Zustand also lets you persist data, meaning that when a user refreshes the page, the data the was previously rendered will still be saved in state. This is a great addition to forms and other pages geared toward user interaction so that progress is not lost.

Conclusion

Zustand is a powerful library that is easy to get started with and offers a simple way to manage state across many components. You can manage async, set re-renders, persist the data, and subscribe to changes in other variables to fully customize your store's function. However, if you are simply looking for an easy, but more functional alternative to useState, you can use Zustand without a lot of extra bells and whistles.

Top comments (0)