Overview
- Local state: input text & todo list
- We keep two independent bits of state: the current text in the input box and the array holding todos.const [text, setText] = useState(""); const [todos, setTodos] = useState([]);
- We keep two independent bits of state: the current text in the input box and the array holding todos.
- Adding a todo immutably
- Trim the text; if it isn’t empty, copy the array and append the new item, then clear the input.const handleAdd = () => { const trimmed = text.trim(); if (!trimmed) return; setTodos([...todos, trimmed]); setText(""); };
- Trim the text; if it isn’t empty, copy the array and append the new item, then clear the input.
- Removing a specific item
- Create a new array that filters out only the clicked index.const handleRemove = (idx) => { setTodos(todos.filter((_, i) => i !== idx)); };
- Create a new array that filters out only the clicked index.
- Rendering UI
- A
<ul>
whose<li>
children map overtodos
, each with a Remove button.<ul data-testid="todo-list" className="space-y-2"> {todos.map((t, i) => ( <li key={i} data-testid="todo-item" className="flex justify-between items-center bg-gray-100 px-3 py-2 rounded" > <span>{t}</span> <button data-testid="remove-btn" onClick={() => handleRemove(i)} className="text-sm font-semibold text-red-600" > ✕ </button> </li> ))} </ul>
- A
import TodoList from "./TodoList"; export default function App() { return ( <div className="min-h-screen bg-gray-50 p-4 flex justify-center"> <TodoList /> </div> ); }
JavaScript Console
console.log()statements will appear here
Tests