Simplifying State Management with React Hooks using Zustand
Tags: react, javascript, zustand, webdev
Published: 2021-05-27 07:37:57


Article originally posted on [my blog](https://www.ankurkedia.com/blog/state-management-zustand).

--- 

State management is probably one of the hardest parts of app development. More importantly, it is also the most crucial part to get right. This article is about simplifying the state management of your app with no new concepts. We will use [Zustand](https://zustand.surge.sh) to solve this which has hooks at its core. Covering the basics in this article, we will create a simple todo app. Since [React Hooks](https://reactjs.org/docs/hooks-intro.html) are used to perform all the operations, basic hooks knowledge is all you'll need to sail through state management with [Zustand](https://github.com/pmndrs/zustand).


## What is Zustand?
Zustand is a simple, lightweight, fast, and React hooks-based state management.

> A small, fast and scaleable barebones state-management solution. Has a comfy API based on hooks, isn't boilerplate-y or opinionated, but still just enough to be explicit and flux-like.


## Features

- Lightweight.
- Little(hooks) or no learning curve. 
- Makes hooks the primary means of consuming state.
- Not opinionated.
- Transient updates.

Apart from the convenience, [Zustand](https://github.com/pmndrs/zustand) solves some of the common problems with other libraries like complex flows, over-engineered solutions. It also solves some common documented issues with major existing libraries and patterns like the [Context loss issue](https://github.com/facebook/react/issues/13332), [React concurrency issues](https://github.com/bvaughn/rfcs/blob/useMutableSource/text/0000-use-mutable-source.md), [Zombie child problem](https://react-redux.js.org/api/hooks#stale-props-and-zombie-children).

## How to use it?
To demonstrate, we will create a basic todo app with CRUD operations. We will start with creating a store. Then, initialize an array of todos and add a function to add a todo to the list.

```js
import create from 'zustand';

const useStore = create((set) => ({
  todos: [],
  add: (title) =>
    set((state) => ({ todos: [...state.todos, { title }] }))
}));
``` 

Then, we attach the state todos we defined in the store to our components.

```js
import { useStore } from './store';

function TodoList() {
  const todos = useStore((state) => state.todos);
  return (
    <div>
      {todos.map(({ title }) => (
        <div>{title}</div>
      ))}
    </div>
  );
}
```
Finally, we attach the add function which we defined to our button element. We will pass the input value as the title for the todo item.

```js
import { useStore } from './store';

function TodoInput() {
  const [inputValue, setInputValue] = React.useState('');
  const add = useStore((state) => state.add);
  return (
    <div>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
      <button onClick={() => add(inputValue)}> Add </button>
    </div>
  );
}
```
Et voila, we have a rudimentary version of the todo app working. The same patterns of `get` and `set` can be used across the app for all sorts of operations. We have also created the `toggleDone` and `remove` functions along the same line. You can check the sandbox below for the complete functionality.

{% codesandbox todo-zustand-react-jbwi0 %}

## Advanced features
For large projects, we need a lot more than just CRUD operations, but Zustand has got you covered there too. It already has support for the following:

- **Async operations**: You just need to call `set` whenever you're ready, it doesn't matter if your actions are async or not.
- **Middlewares**: Compose and pipe your middlewares any way you like.
- **Multiple stores fetching **: You can create as many selectors as you like.
- **Devtools**: Provides an in-built devtool middleware.
- **Usage with Redux**: If you still want to use reducer and action pattern, you can follow it here too.
- **Handling nested states**: Manipulating nested structures is tedious. You can use [immer](https://github.com/immerjs/immer) as a middleware though.


## Disadvantages
Although Zustand's documentation is concise, has a good flow, and is very easy to understand, it could use some more detailing and example in some sections like handling multiple middlewares, managing nested states, code optimizations for better performance. So, please considering contributing to [Zustand](https://github.com/pmndrs/zustand).


> Caution: [You Might Not Need Redux](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367)(or any other state management library)


## Conclusion

Using Zustand is very convenient and you don't need a load of information to get started. When comparing with seasoned state management solutions, it definitely has an edge when it comes to DX. Its simplicity, flexibility, and unopinionated nature make it a compelling option. So, if you are a beginner in handling state management or if you have a project that does not deal with deeply nested structures, then Zustand might be a great fit for your project.