Skip to main content

Command Palette

Search for a command to run...

Zustand

Best State Manager for React

Updated
4 min readView as Markdown
Zustand
O

Hi, my name is oussama and i am a self-taught full stack javascript developer with interests in computers. I like the expend my knowledge and learn new things each day cause i always see the beauty in mystery.

When we have some data to use globally in our react we'll have to use a state manager, and we have many of them like Redux, zustand, etc...

Redux is good yet is complex and have a high learning curve and ofc we want something simple yet powerful to use. This is when zustand shines.

zustand is a light weight state manager for React, with some integrated middleware and its killing feature is what we call `Vanilla State` which allows the state to be used inside and outside components.

Installation

To install zustand into your app , run the follwing

  • npm
    npm i zustand
    
  • yarn
    yarn add zustand
    

to keep a clean folder structure, create a folder called state which will contains different global state for different type of data.

  • example: let's say we want a global count, inside the state folder create a file called count.ts.
import { create } from 'zustand'

type CountState = {
     count: number;
     increaseCount: () => void;
     resetCount: () => void;
}

const useCountStore = create<CountState>()((set) => ({
  count: 0,
  increaseCount: () => set((state) => ({ count: state.count + 1 })),
  resetCount: () => set({ count: 0 }),
}))

export {useCountStore}

Since we use TypeScript , we should obviously type our states.

As you can see in out example we have the state which is count along side methods to control that state, all of this can be called inside any component in your whole app and control the value from anywhere in your app. But keep in mind use global states only when it's necessary. Like saving the user information to use in different places in the app, or a boolean value to toggle some UI globally... if the data change for a specific component you can use local states only.

now let's calls our states.

export const ComponentExample = () => {
     const { count, increaseCount, resetCount } = useCount()

     return (
          <div>
              <button onClick={increaseCount}> + </button>
              <p>{count}</p>
             <button onClick={resetCount}>reset</button>
           </div>
     )
}

Easy isn't it !!! now what if you want to use this state outside a component, in a utils function or an api call for example... simple add vanillaState

let's edit our state file.

import { create } from 'zustand'

type CountState = {
     count: number;
     increaseCount: () => void;
     resetCount: () => void;
}

const vanillaCount = create<CountState>()((set) => ({
  count: 0,
  increaseCount: () => set((state) => ({ count: state.count + 1 })),
  resetCount: () => set({ count: 0 }),
}))

const useCount =  vanillaCount as {
  <T>(): CountState;
  <T, U>(selector: (s: CountState) => U): U;
};

export {useCountStore}

it may look weird but we declared useCount with type assertion to access all props same as vanillaCount since they gonna share the same role

to access values inside state we use the vanillaState like this:

const countValue: number = vanillaCount.getState().count (same way to access methods)

Easy right !!!! Next topic we'll discuss zustand middleware to persist data. Happy Coding <3

Persist Data

OK, let's say you wanted to save the data in localStorage (persist it), as an example will take theme ,switching between dark and light mode and persist the value so it won't get lost when you reload the page.

In this case we can get the help of the persist middleware from zustand

  import { create } from 'zustand'
  import { persist, createJSONStorage } from 'zustand/middleware'

    type ThemeValue = "dark" | "light";

    type ThemeState = {
    theme: ThemeValue;
     setTheme: (value: ThemeValue) => void;
   };

  export const useThemeState = create<ThemeState>(
     persist(
        (set, get) => ({
             theme: "light", // default theme
             setTheme: (value) => set({ theme: value }),
       }),
    {
      name: 'theme-storage', // name of the item in the storage (must be unique)
       storage: createJSONStorage(() => sessionStorage), // localStorage used by default
    },
  ),
)

in the example above we set a global theme state which will allow us to contol and toggle the app theme between dark and light anywhere in our application using the setTheme method.

the value will be saved in localStorage with given name as key.

Easy again LOL !!! That's how powerful and easy zustand is and that's why i love it and use it in most of my application.

Happy learning and coding !!!

More from this blog

Oussama Chahidi's blog

17 posts