DEV Community

Cover image for Building a Dynamic To-Do List with Zustand
Manikanta Ketha
Manikanta Ketha

Posted on

3 1 1 1

Building a Dynamic To-Do List with Zustand

A to-do list is one of the most common applications you’ll encounter in daily life. But what if you could make it dynamic with features like advanced filtering and sorting? In this post, we’ll build a simple to-do list app with Zustand, where users can filter tasks by category and sort them by priority or due date.


Why Zustand?

Zustand is a small, fast, and simple state management tool for React. It works without needing reducers, actions, or context providers. It’s perfect for lightweight applications like our to-do list.


Step 1: Setting Up Zustand Store

Let’s start by creating the Zustand store that will manage the tasks and handle the filtering and sorting.

// todoStore.js
import create from 'zustand';

const useTodoStore = create((set) => ({
  tasks: [],
  filter: 'all',
  sortBy: 'priority',

  addTask: (task) => set((state) => ({ tasks: [...state.tasks, task] })),
  toggleTask: (taskId) => set((state) => ({
    tasks: state.tasks.map((task) =>
      task.id === taskId ? { ...task, completed: !task.completed } : task
    ),
  })),
  setFilter: (filter) => set({ filter }),
  setSortBy: (sortBy) => set({ sortBy }),
}));

export default useTodoStore;
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • tasks: Holds the to-do list.
  • filter: Allows filtering tasks (e.g., show only work tasks).
  • sortBy: Specifies how tasks should be sorted (e.g., by priority or due date).
  • addTask, toggleTask, setFilter, setSortBy: Actions for adding tasks, toggling completion, setting filters, and sorting tasks.

Step 2: Building the UI

Here’s a simple UI to add tasks, filter them, and sort them.

// TodoList.js
import React, { useState } from 'react';
import useTodoStore from './todoStore';

const TodoList = () => {
  const { tasks, filter, sortBy, addTask, toggleTask, setFilter, setSortBy } = useTodoStore();
  const [newTaskText, setNewTaskText] = useState('');
  const [newTaskCategory, setNewTaskCategory] = useState('work');
  const [newTaskPriority, setNewTaskPriority] = useState(1);

  // Filtering and Sorting
  const filteredTasks = tasks.filter((task) => filter === 'all' || task.category === filter);
  const sortedTasks = filteredTasks.sort((a, b) => (sortBy === 'priority' ? b.priority - a.priority : new Date(a.dueDate) - new Date(b.dueDate)));

  const handleAddTask = () => {
    if (newTaskText) {
      addTask({ id: Date.now(), text: newTaskText, completed: false, category: newTaskCategory, priority: newTaskPriority, dueDate: new Date() });
      setNewTaskText('');
    }
  };

  return (
    <div>
      <h2>My To-Do List</h2>
      <input value={newTaskText} onChange={(e) => setNewTaskText(e.target.value)} placeholder="New task..." />
      <select onChange={(e) => setNewTaskCategory(e.target.value)}>
        <option value="work">Work</option>
        <option value="personal">Personal</option>
      </select>
      <select onChange={(e) => setNewTaskPriority(Number(e.target.value))}>
        <option value={1}>High Priority</option>
        <option value={2}>Medium</option>
        <option value={3}>Low Priority</option>
      </select>
      <button onClick={handleAddTask}>Add Task</button>

      <div>
        <button onClick={() => setFilter('all')}>All</button>
        <button onClick={() => setFilter('work')}>Work</button>
        <button onClick={() => setFilter('personal')}>Personal</button>
      </div>

      <div>
        <button onClick={() => setSortBy('priority')}>Sort by Priority</button>
        <button onClick={() => setSortBy('dueDate')}>Sort by Due Date</button>
      </div>

      <ul>
        {sortedTasks.map((task) => (
          <li key={task.id} style={{ textDecoration: task.completed ? 'line-through' : 'none' }} onClick={() => toggleTask(task.id)}>
            {task.text} - {task.category} - {task.priority} - {task.dueDate.toLocaleString()}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. Add New Task: Users can input a new task with category and priority.
  2. Filter Tasks: Buttons allow users to filter by category (Work/Personal).
  3. Sort Tasks: Users can sort tasks by priority or due date.
  4. Task Completion: Clicking a task toggles its completion.

Conclusion

This to-do list app demonstrates how you can create a dynamic and user-friendly task manager using Zustand for state management. We’ve added filtering and sorting to make the list more useful and easier to navigate.

With Zustand’s minimal setup and reactivity, managing state across the app is simple and efficient. Give it a try and start building your own productivity tools!

Top comments (0)