当前位置: 首页 > news >正文

React zustand todos案例(带本地存储localStorage、persist)todoStore.ts

参考文章:React zustand教程(create函数、persist中间件、zustand/middleware、Redux DevTools)查看本地存储localStorage、immer

文章目录

  • 使用 Zustand 构建 Todo 应用完整教程
    • 项目简介
    • 技术栈
    • 项目结构
    • 核心代码解析
      • 1. Zustand Store 定义 (`src/store/todoStore.ts`)
      • 2. 页面组件 (`app/page.tsx`)
      • 3. 配置文件
        • `package.json` 关键依赖
        • `tsconfig.json` 路径别名
    • 复现步骤
      • 步骤 1:创建 Next.js 项目
      • 步骤 2:安装依赖
      • 步骤 3:创建 Store 文件
      • 步骤 4:创建页面组件
      • 步骤 5:运行项目
    • 功能演示
    • 核心概念总结
    • 扩展建议
    • 总结

使用 Zustand 构建 Todo 应用完整教程

项目简介

基于 Next.js 15 和 Zustand 的 Todo 应用,支持:

  • 添加任务
  • 切换完成状态
  • 批量选择/取消选择
  • 删除选中任务
  • 清除已完成的选中任务
  • 数据持久化(localStorage)

在这里插入图片描述

技术栈

  • Next.js 15.5.4
  • React 19.1.0
  • Zustand 5.0.8(状态管理)
  • TypeScript 5
  • Tailwind CSS 4.1.14

项目结构

my-project/
├── app/
│   ├── page.tsx          # 主页面组件
│   ├── layout.tsx        # 根布局
│   └── globals.css       # 全局样式
├── src/
│   └── store/
│       └── todoStore.ts  # Zustand 状态管理
├── package.json
└── tsconfig.json

核心代码解析

1. Zustand Store 定义 (src/store/todoStore.ts)

// src/store/todoStore.ts
import { create } from 'zustand'
import { persist } from 'zustand/middleware'type Todo = { id: string; text: string; done: boolean; selected?: boolean }interface TodoState {todos: Todo[]add: (text: string) => voidtoggle: (id: string) => voidtoggleSelect: (id: string) => voidselectAll: () => voiddeselectAll: () => voidremove: (id?: string) => voidclearDone: () => void
}export const useTodoStore = create<TodoState>()(persist((set) => ({todos: [],add: (text) =>set((state) => ({todos: [...state.todos, { id: Date.now().toString(), text, done: false, selected: false }],})),// 切换完成状态,如果id相同,则done状态取反,否则不变toggle: (id) =>set((state) => ({todos: state.todos.map(t => t.id === id ? { ...t, done: !t.done } : t),})),// 切换选中状态toggleSelect: (id) =>set((state) => ({todos: state.todos.map(t => t.id === id ? { ...t, selected: !t.selected } : t),})),// 全选selectAll: () =>set((state) => ({todos: state.todos.map(t => ({ ...t, selected: true })),})),// 取消全选deselectAll: () =>set((state) => ({todos: state.todos.map(t => ({ ...t, selected: false })),})),// 删除:如果传入id则删除该id,否则删除所有选中的项remove: (id) => {if (id) {set((state) => ({ todos: state.todos.filter(t => t.id !== id) }));} else {set((state) => ({ todos: state.todos.filter(t => !t.selected) }));}},// 清除已完成:删除所有选中的已完成项clearDone: () => set((state) => ({ todos: state.todos.filter(t => !(t.selected && t.done)) })),}),{ name: 'todo-storage' })
)

代码解析:

  • create:创建 Zustand store
  • persist:持久化中间件,数据保存到 localStorage(key: todo-storage
  • Todo:任务类型,包含 idtextdoneselected
  • TodoState:store 接口,包含状态和方法
  • set:更新状态,使用函数式更新保证不可变

方法说明:

  • add:添加任务,使用时间戳作为 id
  • toggle:切换完成状态
  • toggleSelect:切换选中状态
  • selectAll/deselectAll:批量选择/取消
  • remove:删除单个(传 id)或批量删除选中项(不传 id)
  • clearDone:删除已完成的选中项

2. 页面组件 (app/page.tsx)

// page.tsx
'use client'import { useTodoStore } from '@/src/store/todoStore'export default function ProfilePage() {const { todos, add, toggle, remove, clearDone, selectAll, deselectAll, toggleSelect } = useTodoStore()return (<div className="p-8"><div className="flex gap-2"><button onClick={() => add('新任务')}>添加</button><button onClick={() => selectAll()}>全选</button><button onClick={() => deselectAll()}>取消全选</button><button onClick={() => remove()}>删除</button><button onClick={clearDone}>清除已完成</button></div><ul>{todos.map(todo => (<li key={todo.id} className="flex gap-2"><span>id: {todo.id}</span><span>text: {todo.text}</span><span>done: {todo.done ? '已完成' : '未完成'}</span><input type="checkbox" checked={todo.done} onChange={() => toggle(todo.id)} /><span>{todo.selected ? '选中' : '未选中'}</span><input type="checkbox" checked={todo.selected} onChange={() => toggleSelect(todo.id)} /></li>))}</ul></div>)
}

代码解析:

  • 'use client':Next.js 客户端组件
  • useTodoStore():获取 store 状态和方法
  • 按钮:触发对应操作
  • 列表:渲染任务,每个任务显示 id、文本、完成状态、完成复选框、选中状态、选中复选框

3. 配置文件

package.json 关键依赖
  "dependencies": {"@radix-ui/react-slot": "^1.2.3","@tailwindcss/postcss": "^4.1.14","@tanstack/react-query": "^5.90.5","class-variance-authority": "^0.7.1","clsx": "^2.1.1","lucide-react": "^0.545.0","next": "15.5.4","postcss": "^8.5.6","react": "19.1.0","react-dom": "19.1.0","react-error-boundary": "^6.0.0","react-hot-toast": "^2.6.0","react-router-dom": "^7.9.4","tailwind-merge": "^3.3.1","tailwindcss": "^4.1.14","zustand": "^5.0.8"},
tsconfig.json 路径别名
    "paths": {"@/*": ["./*"]}

复现步骤

步骤 1:创建 Next.js 项目

npx create-next-app@latest my-todo-app
# 选择 TypeScript、Tailwind CSS、App Router

步骤 2:安装依赖

npm install zustand

步骤 3:创建 Store 文件

创建 src/store/todoStore.ts,复制上面的 store 代码。

步骤 4:创建页面组件

修改 app/page.tsx,复制上面的页面组件代码。

步骤 5:运行项目

npm run dev

访问 http://localhost:3000 查看效果。

功能演示

  1. 添加任务:点击“添加”按钮,添加一个名为“新任务”的任务
  2. 切换完成状态:点击任务的完成复选框
  3. 选择任务:点击任务的选中复选框
  4. 全选/取消全选:使用顶部按钮
  5. 删除选中:点击“删除”按钮,删除所有选中的任务
  6. 清除已完成:点击“清除已完成”按钮,删除所有已完成的选中任务
  7. 数据持久化:刷新页面后数据仍然保留(存储在 localStorage)

核心概念总结

  1. Zustand:轻量级状态管理,API 简单
  2. 持久化:使用 persist 中间件自动保存到 localStorage
  3. 不可变更新:使用 set 函数式更新,保持状态不可变
  4. TypeScript:类型安全,提供良好的开发体验
  5. 函数式编程:使用 mapfilter 等函数式方法处理数组

扩展建议

  1. 添加输入框:让用户输入自定义任务文本
  2. 编辑功能:支持修改任务内容
  3. 分类功能:为任务添加分类标签
  4. 优先级:添加优先级设置
  5. 日期提醒:添加截止日期功能
  6. UI 优化:使用更美观的 UI 组件库(如 shadcn/ui)

总结

该示例展示了:

  • Zustand 的基本用法
  • 状态持久化
  • TypeScript 类型定义
  • Next.js 客户端组件
  • 函数式状态更新

适合作为学习 Zustand 和状态管理的入门项目。

http://www.dtcms.com/a/606509.html

相关文章:

  • mac配置 unity+vscode的坑
  • 极速网站推广专家wordpress综合网
  • 上海定制网站建设公司网站域名什么意思
  • 【OpenCV + VS】直方图与模糊操作
  • 代码随想录 435.无重叠区间
  • 【AVL树与红黑树】:告别“瘸腿”树,体验平衡的艺术
  • 智慧团建网站入口官网有什么做ppt的网站吗
  • 机器人“小脑”萎缩,何谈“大脑”智慧?六维力/关节力传感器才是“救命稻草”
  • 基于SpringBoot的图书馆管理系统的设计与实现
  • SpringCloud快速通关(中)
  • 性价比高的时序数据库哪个专业
  • 邵阳高端网站建设做响应式网站的物流
  • 网站定制开发哪家厉害网站登录界面源码
  • 自己电脑做网站服务器违法吗上海网站建设最好的公司排名
  • C++-vector-back子函数和std::move函数详细介绍
  • 07.指针
  • 【gas优化】2.9 使用sstore2或sstore3存储大量数据
  • 来宾北京网站建设网站浏览思路
  • 网站建设模式化的体现企业个人邮箱怎么注册
  • 分布式部署
  • 保障电网安全,赋能绿色能源:AM5SE-PV系列主从机防逆流保护装置在江西丰城曲江煤炭开发公司5.8MW分布式光伏项目的关键角色
  • C/C++ Linux网络编程3 - Socket编程与TCP服务器客户端
  • 镇江大港南站wordpress 新闻 通知
  • 【ZeroRange WebRTC】RFC 5389:STUN 协议规范(中文整理与译注)
  • 苏州网站制作及推广二手闲置平台网站怎么做
  • Unity零碎物体合并为一个整体mesh
  • 做响应式网站图片需要做几版在哪个网站找学做包子
  • 国内大型php网站建设商务网站开发背景
  • HarmonyOS开发-ArkWeb开发指导
  • kotlin:if、when语句介绍