- read

React Context is Officially Dead; Enter Zustand State Management.

Daniel Craciun 51

React Context is Officially Dead; Enter Zustand State Management.

Daniel Craciun
Level Up Coding
Published in
5 min readAug 21

--

Photo by Lautaro Andreani on Unsplash

In the ever-evolving landscape of frontend development, React Context has long been a stalwart for state management.

However, the winds of change are blowing as a new contender steps onto the scene: Zustand. In this article, we delve into Zustand by creating a basic interactive todo application.

We’ll take a close look at how Zustand reimagines state management, its core principles, and how it addresses some of the pain points that developers have faced with React Context.

Ready? Lets get started!

Table of Contents

  • Setting Up A React/Next.js Project
  • Dependencies Installation
  • Creating Our Global Zustand Store
  • Using Our Zustand Store

Setting Up A React/Next.js Project

  1. Before you begin, you will need to setup a Next.js 13 or basic React app. Both will work just fine as Next.js supports React client components.

Dependencies Installation

  1. The dependencies required for this project is minute, in fact you will only need to install two packages; the zustand package, and uuid.
# we will need 'uuid' later to assign unique id's to our 
# todos

npm i zustand uuid
pnpm add zustand uuid
yarn add zustand uuid

Creating Our Global Zustand Store

Now that the groundwork is complete, lets get coding.

  1. Begin by creating a file called useTodosStore.ts anywhere in your project workspace.
  2. Copy the following code; it’s quite a mouthful, but we’ll break it down shortly.
import { v4 as uuid } from "uuid"
import { create } from "zustand"

type Todo = {
id: string
checked: boolean
}

export type Todos = Todo[] | null

interface TodosState {
todos: Todos
setTodos: (todos: Todos) => void
addTodo: () => void
removeTodo: (id: string) => void
updateTodoChecked: (id: string) => void
}

export const useTodosStore = create<TodosState>((set) => ({
todos: null,
// Simply takes in a todos list as a parameter and updates the todos
// state with that value.
setTodos: (todos) => set(() => ({ todos })),

// a new array 'updatedTodos' is created by removing a todo with a matching
// 'id' property.
removeTodo: (id) =>
set(({ todos }) => {
const updatedTodos = todos!.filter((todo) => todo.id !== id)
return { todos: updatedTodos }
}),
// Creates a new Todo object and appends it to the current todos state.
addTodo: () =>
set(({ todos }) => {
const newTodo: Todo = { id: uuid(), checked: false }
if (todos?.length) {
return { todos: [...todos, newTodo] }
} else {
return { todos: [newTodo] }
}
}),
// Searches for the todo in the todos array by id, then
// negates the current checked value and updates the state.
updateTodoChecked: (id) =>
set(({ todos }) => {
const updatedTodos = todos!.map((todo) => {
if (todo.id === id) {
return {
...todo,
checked: !todo.checked,
}
}
return todo
})

return { todos: updatedTodos }
}),
}))
  • Firstly we import create from zustand, which is a function that allows us to create our global state, as well as uuid to generate unique id’s for each todo.
  • We define a custom type Todo which has a unique id as well as a checked property.
  • We define another custom type Todos that represents our array of Todo objects or it could also be null, representing no todos.
  • Next we define the global store useTodosStore of generic type TodosState which containing the blueprint of our todos state and our functions to add, remove, set, and update todos.
  • Inside our store, we define our initial todos state, which is null in this case, representing no todos.
  • We then define the four state functions as shown; look at the comments for further explanations.

Using Our Zustand Store

I hope your still with me at this point. I chose this example because I feel like it’s made for zustand like bread is made for butter. This example therefore gives me the opportunity to fully showcase the power of zustand state management.

  1. Open a file in React/Next.js where you can render a component, in my case I create a page.tsx file which is treated as a web page in Next.js 13.
  2. Copy the following code:
// Only include this in Next.js
"use client"

import { useEffect } from "react"

import { useTodosStore } from "path-to-your-useTodosStore-file"

const Page = () => {
// Defines the global zustand state along with all it's functions
const { todos, setTodos, removeTodo, addTodo, updateTodoChecked } = useTodosStore()

// Begin by showing 1 todo on initial page render which is unchecked.
useEffect(() => {
setTodos([{ id: "1", checked: false }])
}, [])
return (
<div>
{todos?.map((todo) => (
<div className="flex">
<input
type="checkbox"
checked={todo.checked}
onChange={() => updateTodoChecked(todo.id)}
/>
<button onClick={() => removeTodo(todo.id)}>
Remove this todo -
</button>
</div>
))}
<button onClick={() => addTodo()}>Add a new todo +</button>
</div>
)
}

export default Page
  • Simple right? We are importing the global state within our file, we then initialize the todos state with one todo, followed by rendering the todos, which are now fully interactive and stateful. Test it for yourself!

Here is an example of how it may look with proper styling applied:

My custom todos feature; beautifully styled and interactive.
My custom todos feature; beautifully styled and interactive.
  • In the above example I made use of a ‘text input’ as well as the features we covered in this article.
  • CHALLENGE: update the useTodosStore.ts file using what you’ve learnt to create a new state function updateTodoText that manages the state of a ‘text input’ field for each todo. Then update your page to render each input field.

Congratulations! You are now a certified zustand pro!

I hope I've convinced you of the many benefits of zustand using the common todos example, and hopefully I’ve convinced you to put React Context in the past.

If you enjoyed this article, check out my profile for many more stories like this, and stay tuned for future articles! 👍

Level Up Coding

Thanks for being a part of our community! Before you go:

🔔 Follow us: Twitter | LinkedIn | Newsletter

🚀👉 Join the Level Up talent collective and find an amazing job