Published on

Simplify your store! A brief introduction to Zustand

4 min read

Authors
banner

State management has always been opinionated in React community. Redux was a revolutionary tech for the React ecosystem when it was first released. It allowed applications to have a global store that was immutable and solved challenges like prop drilling elegantly. To this day, it continues to be great and scalable.

I've used redux and similar solutions for years and one thing that always bothered me was the amount of boilerplate required to get started with it. Redux toolkit largely solves the boilerplate issue but when compared to excellent solutions like MobX, MST it still seemed verbose for small to medium size projects.

A couple of weeks ago I wanted to refactor a decent sized write-heavy context state to a better solution, and naturally Redux, MobX came to mind. However, I wanted something simpler and more elegant.

Zustand to the rescue!!

As stated in the docs, "Zustand is a small, fast and scaleable barebones state-management solution. Has a comfy api based on hooks, isn't boilerplatey or opinionated, but still just enough to be explicit and flux-like".

What really motivated me to use Zustand was how simple it was to get started with it and great features like transient updates for often occurring state changes, memorized selectors, integration with immer! and the best no Providers!!

Let's go over a basic store example with Zustand using Typescript.

Install zustand

yarn add zustand

Creating a store

import create, { SetState, GetState } from 'zustand';

type CountStore {
  count: number;
  increment: () => void;
};

const useCountStore = create<CountStore>((set: SetState<CountStore>, get: GetState<CountStore>) => ({
  count: 0,
  increment: (): void =>  {
    const { count } = get();
    set({ count: count + 1 });
  }
});

create gives two arguments set and get. The set function (you guessed it right!) merges the state, similar to setState in class-based react components. And through the get function we can access the current state of the store, especially helps when we want to access the state within an action. Quite useful!

Usage with components

Now, let's see how we can make use of our store in a component using hooks!

function Counter(): React.ReactElement {
  const count = useCountStore(state => state.count);
  const increment = useCountStore(state => state.increment);

  return (
    <div>
      <h1>count: {count}</h1>
      <button onClick={increment}>+1</button>
    </div>
  );
}

The store itself acts as a selector hook! Neat. We can also do multiple selects for the same.

const [count, increment] = useCountStore(state => [
  state.counter,
  state.increment,
]);

And that's it, we now have a simple store without any extra boilerplate code.

We haven't even scratched the surface with zustand yet. There are tons of amazing features like transient updates, immer integration, memorized selectors, async actions, middleware...and the list goes on. I feel they are better explained in the docs

Hopefully, this article helps as a brief introduction to Zustand. So far I am really enjoying using it.

Are you using Zustand already? Or want to talk all things javascript with me? Find me on twitter @karan_6864

© 2024 Karan Pratap Singh