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 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 are used to perform all the operations, basic hooks knowledge is all you'll need to sail through state management with 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.
Apart from the convenience, 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, React concurrency issues, Zombie child problem.
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.
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.
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.
import { useStore } from './store';function TodoInput() {const [inputValue, setInputValue] = React.useState('');const add = useStore((state) => state.add);return (<div><inputvalue={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. Our store looks like the code below. For complete functionality, check the codesandbox link below.
import create from "zustand";const useStore = create((set) => ({todos: [],add: (title) =>set((state) => ({ todos: [...state.todos, { title }] })),toggleDone: (index) =>set((state) => ({todos: state.todos.map((todo, id) => {if (index !== id) {return todo;}return { ...todo, done: !todo.done };})})),remove: (index) =>set((state) => ({todos: state.todos.filter((todo, id) => id !== index)}))}));
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:
set
whenever you're ready, it doesn't matter if your actions are async or not.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.
Caution: You Might Not Need Redux (or any other state management library)
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.
Views 8339
Discuss on Twitter