1 npx create-next-app@latest
Try Run
Create DIR components
in src/
Create File AddToDo.tsx
in src/components
. Create File TodoFilter.tsx
in src/components
. Create File ToDoItem.tsx
in src/components
. Create File ToDoList.tsx
in src/components
.
Create File types.ts
in src/
.
type.ts
1 2 3 4 5 export interface Todo { id : number; text : string; completed : boolean; }
AddTodoProps.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import { useState } from "react" ; interface AddTodoProps { addTodo : (text: string ) => void ; }function AddTodo ({ addTodo }: AddTodoProps ) { const [text, setText] = useState ("" ); const handleSubmit = (e: React.FormEvent ) => { e.preventDefault (); if (text.trim () === '' ) { return } addTodo (text) setText ('' ) } return ( <form onSubmit ={handleSubmit} > <input type ="text" value ={text} onChange ={(e) => setText(e.target.value)} /> <button > 新建事项</button > </form > ); }export default AddTodo ;
ToDoFilter.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 interface TodoFilterProps { setFilter : (filter: string ) => void ; }function TodoFilter ({ setFilter }: TodoFilterProps ) { return ( <div > <button onClick ={() => setFilter('all')}>全部</button > <button onClick ={() => setFilter('active')}>待办</button > <button onClick ={() => setFilter('completed')}>已完成</button > </div > ); }export default TodoFilter ;
TodoItem.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import { Todo } from "@/types" ; interface TodoItemProps { todo : Todo ; toggleTodo : (id: number ) => void ; deleteTodo : (id: number ) => void ; }function TodoItem ({ todo, toggleTodo, deleteTodo }: TodoItemProps ) { return ( <li style ={{ textDecoration: todo.completed ? 'line-through ' : 'none ' }}> {todo.text} <button onClick ={() => toggleTodo(todo.id)}>切换</button > <button onClick ={() => deleteTodo(todo.id)}>删除</button > </li > ); }export default TodoItem ;
Create types.ts
in src/
1 2 3 4 5 export interface Todo { id : number; text : string; completed : boolean; }
TodoList.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import TodoItem from "./TodoItem" ;import { Todo } from "@/types" ; interface TodoListProps { todos : Array <Todo >; toggleTodo : (id: number ) => void ; deleteTodo : (id: number ) => void ; }function TodoList ({ todos, toggleTodo, deleteTodo }: TodoListProps ) { return ( <ul > {todos.map((todo) => ( <TodoItem key ={todo.id} todo ={todo} toggleTodo ={toggleTodo} deleteTodo ={deleteTodo} /> ))} </ul > ); }export default TodoList ;
完成效果: