今天我們要來實現刪除 Todo
的功能。以下程式碼會先透過 props
傳遞來實作,目的是熟練前幾章節所學到的技能。請不用擔心,之後我們會慢慢優化這些功能。
由於我們目前的資料並沒有儲存在資料庫,而是單純透過 React 狀態來儲存,因此我們不是真的在“刪除”資料,而是使用 JavaScript 的 filter 方法來篩選出需要保留的內容。
首先,在 App.tsx
中定義 deleteTodoHandler
函式。filter
方法會返回一個新的陣列,因此下方程式碼的作用是排除被刪除的 todo
,並將回傳的陣列設為新的 todos
:
const deleteTodoHandler = (id: number) => {
setTodos((prevTodos) => prevTodos.filter((todo) => todo.id !== id))
}
接著,將 deleteTodoHandler
傳遞給 TodoList
。我們使用 on
作為函式名稱的開頭,這是命名 函式 props
的慣例:
<TodoList todos={todos} onDeleteTodo={deleteTodoHandler} />
在 TodoList
中,我們需要將接收到的 onDeleteTodo
函式加入自定義的型別。該函式接收一個 id
(數字型別)作為參數,並且不返回任何值:
type TodoListProps = {
todos: TodoItem[]
onDeleteTodo: (id: number) => void
}
接著,我們將 onDeleteTodo
作為 props
傳遞給 Todo
元件。這裡要特別注意的是,先前的實作中,Todo
元件並沒有接收 id
,但刪除 todo
需要 id
,因此我們除了傳遞函式外,也需要傳遞 id
:
export default function TodoList({ todos, onDeleteTodo }: TodoListProps) {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id} className='list-none'>
<Todo
isFinished={todo.isFinished}
id={todo.id}
onDelete={onDeleteTodo}
>
<p>{todo.title}</p>
</Todo>
</li>
))}
</ul>
)
}
在自定義的型別中,我們需要新增 id
和 onDelete
函式:
type TodoProps = PropsWithChildren<{
isFinished: boolean
id: number
onDelete: (id: number) => void
}>
接著,在 props
中新增 id
與 onDelete
函式,並在刪除按鈕上綁定點擊事件:
export default function Todo({
isFinished,
children,
id,
onDelete,
}: TodoProps) {
return (
<div className='flex items-center gap-[20px] justify-between mb-3'>
<input type='checkbox' checked={isFinished} />
{children}
<div className='flex gap-[16px]'>
<button>Edit</button>
<button
onClick={() => {
onDelete(id)
}}
>
Delete
</button>
</div>
</div>
)
}
打開瀏覽器並前往 http://localhost:5173/,現在你應該可以在畫面上自由執行刪除功能。