{"author":{"address":null,"user":"https://learnblockchain.cn/people/23988"},"content":{"body":"![88f9d4b7250a724489ed6e23ff6ea7f.jpg](https://img.learnblockchain.cn/attachments/2025/01/zDGMnQL26788ea1ea25b3.jpg)\r\n请关注 **sui** 前端共学营及其社区，在这里你可以学到前端和 **move** 合约语言的知识。-\r\n## 创建项目\r\n这次使用next框架搭建react项目\r\n`npx create-next-app@latest`\r\n进入目录启动\r\n`npm run dev`\r\n\r\n可以先进入到`src/app/page.tsx`删除他的默认代码便于后续代码书写\r\n## 组件设计\r\n可以将此TodoList项目拆开为几个组件。\r\n- TodoList   用于展示Todo\r\n- AddTodo 用于增减Todo\r\n- TodoItem Todo项目\r\n- TodoFilter 用于筛选Todo\r\n\r\n在`src`目录下创建`components`组件文件夹在其内创建上面四个tsx文件，先在每个文件写导出的函数（下有参考），然后在page中引用。\r\n```tsx\r\nfunction TodoList() {\r\n    return (\r\n        \u003c\u003e\r\n            \u003ch1\u003eTodo List\u003c/h1\u003e\r\n        \u003c/\u003e\r\n    )\r\n}\r\n\r\nexport default TodoList;\r\n```\r\n导入到page使用\r\n```tsx\r\nimport Image from \"next/image\";\r\nimport styles from \"./page.module.css\";\r\nimport TodoList from \"@/components/TodoList\";\r\nimport AddTodo from \"@/components/AddTodo\";\r\nimport TodoItem from \"@/components/TodoItem\";\r\nimport TodoFilter from \"@/components/TodoFilter\";\r\n\r\nexport default function Home() {\r\n  return (\r\n    \u003c\u003e\r\n      \u003ch1\u003eTodoList\u003c/\u003e\r\n      \u003cAddTodo\u003e\u003c/AddTodo\u003e\r\n      \u003cTodoList\u003e\u003c/TodoList\u003e\r\n      \u003cTodoFilter\u003e\u003c/TodoFilter\u003e\r\n    \u003c/\u003e\r\n  );\r\n}\r\n```\r\n## 状态设置和处理\r\nTodo一个数组结构，我们需要设置个状态对其进行管理，这里使用`useState`默认值就是空数组，我们需要去考虑他所使用的类型。我们可在文档中做记录在`src`下创建`types.ts`\r\nTodo\r\n```ts\r\nexport interface Todo {\r\n  id: number;\r\n  text: string;\r\n  completed: boolean;\r\n}\r\n```\r\n状态管理\r\n```ts\r\nconst [todos, setTodos] = useState\u003cTodo[]\u003e([]);\r\n```\r\n下面封装对Todo的处理\r\naddTodo：\r\n```ts\r\n  const addTodo = (text: string) =\u003e {\r\n    const newTodos = {\r\n      id: Date.now(),\r\n      text,\r\n      completed: false,\r\n    }\r\n    setTodos([...todos, newTodos]);\r\n  }\r\n```\r\ndeleteTodo：\r\n```ts\r\nconst deleteTodo = (id: number) =\u003e {\r\n    setTodos(todos.filter((todo) =\u003e todo.id !== id));\r\n  }\r\n```\r\ntoggleTodo\r\n```js\r\n  const toggleTodo = (id: number) =\u003e {\r\n    setTodos(todos.map(todo =\u003e {\r\n      if (todo.id === id) {\r\n        todo.completed = !todo.completed;\r\n      }\r\n      return todo;\r\n    }))\r\n  }\r\n```\r\nTodoFilter\r\n这个`filter`更改当前TodoList列表，交互改变其状态这里需要到设一个状态默认值\"all\"展现所有`Todo`\r\n```ts\r\nconst [filter, setFilter] = useState(\"all\");\r\n  const getFilteredTodos = () =\u003e {\r\n    switch (filter) {\r\n      case \"all\":\r\n        return todos;\r\n      case \"active\":\r\n        return todos.filter(todo =\u003e !todo.completed);\r\n      case \"completed\":\r\n        return todos.filter(todo =\u003e  todo.completed);\r\n      default:\r\n        return todos;\r\n    }\r\n  }\r\n```\r\n## 组件功能\r\n```tsx\r\nexport default function Home() {\r\n  return (\r\n    \u003c\u003e\r\n      \u003ch1\u003eTodo List\u003c/\u003e\r\n      \u003cAddTodo addTodo={addTodo}\u003e\u003c/AddTodo\u003e\r\n      \u003cTodoList todos={getFilteredTodos()} deleteTodo={deleteTodo} toggleTodo={toggleTodo}\u003e\u003c/TodoList\u003e\r\n      \u003cTodoFilter filter={filter} setFilter={setFilter}\u003e\u003c/TodoFilter\u003e\r\n    \u003c/\u003e\r\n  );\r\n}\r\n```\r\nAddTodo（这里可能会报错需要在page中加\"use client\"）\r\n```ts\r\nimport React, { useState } from \"react\";\r\ninterface AddTodoProps {\r\n    addTodo: (text: string) =\u003e void;\r\n}\r\n\r\nfunction AddTodo({addTodo}: AddTodoProps) {\r\n    const [text, setText] = useState('');\r\n    const handleSubmit = (e: React.FormEvent\u003cHTMLFormElement\u003e) =\u003e {\r\n        e.preventDefault();\r\n        if (text.trim() === '') {\r\n            return\r\n        }\r\n        addTodo(text)\r\n        setText('')\r\n    }\r\n    return (\r\n        \u003c\u003e\r\n         \u003cform onSubmit={handleSubmit}\u003e\r\n            \u003cinput\r\n                type=\"text\"\r\n                value={text}\r\n                onChange={(e) =\u003e setText(e.target.value)}\r\n            /\u003e\r\n            \u003cbutton\u003e新建事项\u003c/button\u003e\r\n         \u003c/form\u003e\r\n        \u003c/\u003e\r\n    )\r\n}\r\n\r\nexport default AddTodo;\r\n```\r\nTodoList\r\n```ts\r\nimport {Todo} from '../types';\r\nimport TodoItem from './TodoItem';\r\ninterface TodoListProps {\r\n    todos: Array\u003cTodo\u003e;\r\n    toggleTodo: (id: number) =\u003e void;\r\n    deleteTodo: (id: number) =\u003e void;\r\n}\r\n\r\nfunction TodoList({todos, toggleTodo, deleteTodo }: TodoListProps) {\r\n    return (\r\n        \u003c\u003e\r\n            \u003cul\u003e\r\n                {todos.map(todo =\u003e (\r\n                    \u003cTodoItem key={todo.id} todo={todo} toggleTodo={toggleTodo} deleteTodo={deleteTodo}\u003e\u003c/TodoItem\u003e\r\n                ))}\r\n            \u003c/ul\u003e\r\n        \u003c/\u003e\r\n    )\r\n}\r\n\r\nexport default TodoList;\r\n```\r\nTodoItem\r\n```ts\r\nimport {Todo} from \"../types\";\r\ninterface TodoListProps {\r\n    todos: Array\u003cTodo\u003e;\r\n    toggleTodo: (id: number) =\u003e void;\r\n    deleteTodo: (id: number) =\u003e void;\r\n}\r\n\r\nfunction TodoItem({todo, toggleTodo, deleteTodo}: any) {\r\n    return (\r\n        \u003cli style={{textDecoration: todo.completed ? \"line-through\" : \"none\"}}\u003e\r\n            {todo.text}\r\n            \u003cbutton onClick={() =\u003e toggleTodo(todo.id)}\u003eToggle\u003c/button\u003e\r\n            \u003cbutton onClick={() =\u003e deleteTodo(todo.id)}\u003eDelete\u003c/button\u003e\r\n        \u003c/li\u003e\r\n    )\r\n}\r\n\r\nexport default TodoItem;\r\n```\r\nTodoFilter\r\n```ts\r\nfunction TodoFilter({setFilter}:any) {\r\n    return (\r\n        \u003cdiv\u003e\r\n            \u003cbutton onClick={()=\u003esetFilter('all')}\u003eAll\u003c/button\u003e\r\n            \u003cbutton onClick={()=\u003esetFilter('active')}\u003eactive\u003c/button\u003e\r\n            \u003cbutton onClick={()=\u003esetFilter('completed')}\u003ecompleted\u003c/button\u003e\r\n        \u003c/div\u003e\r\n    )\r\n}\r\n\r\nexport default TodoFilter;\r\n```\r\n\r\n![屏幕录制 2025-01-19 221449.gif](https://img.learnblockchain.cn/attachments/2025/01/Wn6yL2e2678d0a8d8fa90.gif)","title":"【Sui】前端共学React学习笔记（4）"},"history":null,"timestamp":1737296751,"version":1}