通过React实现简单的待办事项列表

97 阅读3分钟

原码

'use client'

import React, { useState } from 'react'
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { Trash2, Edit2 } from 'lucide-react'

interface Todo {
  id: number
  text: string
}

export default function TodoList() {
  const [todos, setTodos] = useState<Todo[]>([])
  const [inputValue, setInputValue] = useState('')
  const [editingId, setEditingId] = useState<number | null>(null)

  const addTodo = () => {
    if (inputValue.trim() !== '') {
      if (editingId !== null) {
        setTodos(todos.map(todo => 
          todo.id === editingId ? { ...todo, text: inputValue } : todo
        ))
        setEditingId(null)
      } else {
        setTodos([...todos, { id: Date.now(), text: inputValue }])
      }
      setInputValue('')
    }
  }

  const deleteTodo = (id: number) => {
    setTodos(todos.filter(todo => todo.id !== id))
  }

  const editTodo = (id: number) => {
    const todoToEdit = todos.find(todo => todo.id === id)
    if (todoToEdit) {
      setInputValue(todoToEdit.text)
      setEditingId(id)
    }
  }

  return (
    <div className="max-w-md mx-auto mt-10 p-6 bg-white rounded-lg shadow-xl">
      <h1 className="text-2xl font-bold mb-4">待办事项列表</h1>
      <div className="flex mb-4">
        <Input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          placeholder="添加新的待办事项"
          className="flex-grow mr-2"
        />
        <Button onClick={addTodo}>
          {editingId !== null ? '更新' : '添加'}
        </Button>
      </div>
      <ul className="space-y-2">
        {todos.map(todo => (
          <li key={todo.id} className="flex items-center justify-between bg-gray-100 p-2 rounded">
            <span>{todo.text}</span>
            <div>
              <Button variant="ghost" size="icon" onClick={() => editTodo(todo.id)}>
                <Edit2 className="h-4 w-4" />
              </Button>
              <Button variant="ghost" size="icon" onClick={() => deleteTodo(todo.id)}>
                <Trash2 className="h-4 w-4" />
              </Button>
            </div>
          </li>
        ))}
      </ul>
    </div>
  )
}

image.png

image.png

这个TodoList组件实现了以下功能:

  1. 添加新的待办事项: 用户可以在输入框中输入新的待办事项,然后点击"添加"按钮或按回车键来添加。
  2. 编辑待办事项: 用户可以点击编辑图标来编辑现有的待办事项。编辑时,输入框会被填充with当前待办事项的文本,按钮文本会变为"更新"。
  3. 删除待办事项: 用户可以点击删除图标来删除待办事项。
  4. 列表显示: 所有的待办事项都会以列表的形式显示出来。
  5. 响应式设计: 使用了Tailwind CSS类来确保组件在不同屏幕尺寸下都能良好显示。
  6. 使用shadcn/ui组件: 使用了InputButton组件来增强用户界面。
  7. 图标: 使用了Lucide React的Trash2Edit2图标来表示删除和编辑操作。

要使用这个组件,可以将它导入到主页面。例如,在app/page.tsx文件中:

import TodoList from '../components/TodoList'

export default function Home() {
  return (
    <main className="min-h-screen bg-gray-100 py-6 flex flex-col justify-center sm:py-12">
      <TodoList />
    </main>
  )
}

代码实现方法

  1. 状态管理: 我们使用React的useState钩子来管理三个主要的状态:

    • todos:一个数组,存储所有的待办事项。
    • inputValue:一个字符串,记录输入框的当前值。
    • editingId:一个数字或null,表示当前正在编辑的待办事项的ID。
  2. 添加和更新功能: 当用户点击"添加"或"更新"按钮时,我们检查输入框是否为空。如果不为空,我们会根据是否有正在编辑的项目来决定是添加新项目还是更新现有项目。

  3. 删除功能: 当用户点击删除按钮时,我们通过过滤掉指定ID的待办事项来从列表中移除该项目。

  4. 编辑功能: 当用户点击编辑按钮时,我们找到对应的待办事项,将其文本填充到输入框中,并设置editingId为该项目的ID。

  5. 渲染: 我们使用JSX来描述组件的结构。主要包括一个标题、一个输入框、一个添加/更新按钮,以及一个待办事项列表。每个待办事项都有自己的编辑和删除按钮。

  6. 列表渲染: 我们使用JavaScript的map函数来遍历todos数组,为每个待办事项创建一个列表项。

  7. 条件渲染: 我们根据是否有正在编辑的项目来决定主按钮显示"添加"还是"更新"。