State management is an essential aspect of building modern web applications. It allows developers to manage and update the application’s state effectively, leading to better user experiences. There are many state management libraries available for React, but they often come with a steep learning curve or require a lot of boilerplate code. Zustant is the easiest and most flexible state management library I tested so far.

In this article we will be using Zustand to manage the state of a simple todo application.

Getting started with Zustand

To get started with Zustand, you need to install it as a dependency in your project. You can do this by running the following command in your terminal:

npm install zustand

Creating a store

Once you have installed Zustand, you can create a store to manage your application’s state. A store is an object that holds the state of your application and provides methods to update that state. Here’s the code for our todo store:

// store.ts
import { create } from "zustand";

export interface TodoItem {
  id: string;
  name: string;
}

export interface TodoState {
	items: TodoItem[];
	addItem: (item: TodoItem) => void;
	removeItem: (id: string) => void;
}

const useTodoStore = create<TodoState>((set) => ({
	items: [],
	addItem: (item) => {
		return set((state) => ({ items: [...state.items, item] }));
	},
	removeItem: (id) => {
		return set((state) => ({
			items: state.items.filter((item) => item.id !== id),
		}));
	},
}));

export default useTodoStore;

Using the store

Now it’s time to use our store in our React application. Here’s the code:

// App.tsx
import { useState } from "react";
import useTodoStore from "./store";

function App() {
  const [todoText, setTodoText] = useState("");
  const { items, addItem, removeItem } = useTodoStore();

  return (
    <div className="App">
      <h1>TODO</h1>

      {items.length ? (
        <ul>
          {items.map((item) => (
            <li key={item.id}>
              {item.name}

              <button onClick={() => removeItem(item.id)} aria-label="Remove">
                Remove
              </button>
            </li>
          ))}
        </ul>
      ) : (
        <p>No items</p>
      )}

      <form onSubmit={(event) => {
          event.preventDefault();

          addItem({
            id: `${Date.now()}`,
            name: todoText,
          });

          setTodoText("");
        }}
      >
        <input type="text" placeholder="New TODO item" value={todoText} onChange={(e) => setTodoText(e.target.value)} />
        <button type="submit" disabled={!todoText}>
          Add
        </button>
      </form>
    </div>
  );
}

export default App;

Pretty simple! all we need to do is import our store and use it in our React components. A full working example of this todo application can be found on CodeSandbox.