Reactjs Todo List App (Using Vite & Zustand)

Jagroop Singh - Sep 16 - - Dev Community

When building a ReactJS application, managing state efficiently becomes crucial as the app scales. React’s built-in state management is great for small apps, but for larger or more complex applications, an external state management library often becomes necessary.
Zustand is one such lightweight, fast, and minimalistic state management library that can help you manage global states in your React application without adding much complexity.

In this blog, we'll learn how to use Zustand in a simple Todo List App built using Vite.

Here is the working of project:

Screen of Adding Todo List

Screen to Delete Todo's (if completed)

Marking completed for Completed todo

What is Zustand?

Zustand is a small, fast state management library for React. It provides a simpler API compared to other state management libraries like Redux, making it more user-friendly for small to mid-sized applications.

Why Zustand?

  • Simplicity: Zustand provides a simple and minimal API to work with state.
  • Performance: Zustand only triggers re-renders in components that use the specific state that has changed.
  • No Boilerplate: Unlike Redux, Zustand doesn’t require reducers, actions, or middleware to manage the state.

Getting Started with Zustand and Vite

Step 1: Create a New Project with Vite
First, let’s set up a React project using Vite, which is a fast and modern build tool.

# Create a new Vite project
npm create vite@latest todo-app-zustand --template react
Enter fullscreen mode Exit fullscreen mode

Then follow below steps in terminal:

selecting reactjs

choosing javascript

Then follow below commands :

# Move into the project directory
cd todo-app-zustand

# Install dependencies
npm install
Enter fullscreen mode Exit fullscreen mode

Vite has now created a boilerplate React app. You can run the app using:

npm run dev

Enter fullscreen mode Exit fullscreen mode

Open http://localhost:5173 in your browser to see your new Vite app running.


Step 2: Install Zustand
Now, let's install Zustand to manage the state of our Todo list app.

npm install zustand
Enter fullscreen mode Exit fullscreen mode

Step 3: Set Up Zustand for State Management

Create a new folder called store in your src directory and add a file todoStore.js inside it. This file will hold our Zustand store.

// src/store/todoStore.js
import { create } from 'zustand';

const useTodoStore = create((set) => ({
  todos: [],

  // Add a new todo
  addTodo: (todo) =>
    set((state) => ({
      todos: [...state.todos, { id: Date.now(), text: todo, completed: false }],
    })),

  // Remove a todo by ID
  removeTodo: (id) =>
    set((state) => ({
      todos: state.todos.filter((todo) => todo.id !== id),
    })),

  // Toggle a todo's completion status
  toggleTodo: (id) =>
    set((state) => ({
      todos: state.todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      ),
    })),
}));

export default useTodoStore;

Enter fullscreen mode Exit fullscreen mode
  • addTodo: Adds a new todo to the list.
  • removeTodo: Removes a todo by its unique id.
  • toggleTodo: Toggles the completed status of a todo.

Step 4: Create the Todo List Component
Now, we will create a TodoList component that interacts with Zustand's state.

// src/components/TodoList.jsx
import React, { useState } from 'react';
import useTodoStore from '../store/todoStore';

const TodoList = () => {
  const { todos, addTodo, removeTodo, toggleTodo } = useTodoStore();
  const [newTodo, setNewTodo] = useState('');

  const handleAddTodo = () => {
    if (newTodo.trim()) {
      addTodo(newTodo);
      setNewTodo(''); // Clear the input after adding
    }
  };

  return (
    <div>
      <h1>Todo List</h1>
      <input
        type="text"
        value={newTodo}
        onChange={(e) => setNewTodo(e.target.value)}
        placeholder="Add a new todo"
      />
      <button onClick={handleAddTodo}>Add</button>

      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>
            <span
              style={{
                textDecoration: todo.completed ? 'line-through' : 'none',
                cursor: 'pointer',
              }}
              onClick={() => toggleTodo(todo.id)}
            >
              {todo.text}
            </span>
            <button onClick={() => removeTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

Enter fullscreen mode Exit fullscreen mode

Here, we are using the useTodoStore hook to:

  • Fetch the list of todos.
  • Add new todos.
  • Toggle the completion status of a todo.
  • Delete a todo

Step 5: Add TodoList Component to App
Now, we need to add our TodoList component to the main App.jsx file.

// src/App.jsx
import React from 'react';
import TodoList from './components/TodoList';

function App() {
  return (
    <div className="App">
      <TodoList />
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Step 6: Styling (Optional)
You can optionally style your app using your preferred CSS framework, or even install and use Tailwind CSS or Bootstrap.

For simplicity, let's add some basic styles directly in index.css.

/* src/index.css */
body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 20px;
  background-color: #f4f4f4;
}

h1 {
  text-align: center;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: flex;
  justify-content: space-between;
  background: #fff;
  margin: 10px 0;
  padding: 10px;
  border-radius: 5px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

button {
  background: #ff4757;
  border: none;
  color: white;
  padding: 5px 10px;
  cursor: pointer;
}

input {
  margin-right: 10px;
  padding: 5px;
  width: 300px;
}

Enter fullscreen mode Exit fullscreen mode

Step 7: Run Your App
Run the app using:

npm run dev
Enter fullscreen mode Exit fullscreen mode

You should now see a functional Todo list where you can:

  • Add new todos.
  • Mark todos as completed or uncompleted by clicking on them.
  • Delete todos.

Conclusion:
In this tutorial, we built a simple Todo List app using React and Zustand for state management.

  • Zustand’s simplicity and performance make it a great choice for managing state in small to medium-sized applications.
  • It requires far less boilerplate compared to other state management solutions like Redux.
  • By using Zustand, you can focus on building your application logic without worrying about managing unnecessary complexity.

That's all for this blog! Stay tuned for more updates and keep building amazing apps! 💻✨
Happy coding! 😊

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .