Hooks & State — Beginner React challenge.
Build a classic todo list with full CRUD functionality — create new todos, read/display them, update their text or completed state, and delete them — all using plain useState.
Requirements
- A text input + Add button creates a new todo; empty/whitespace-only input is ignored and the input clears after a successful add.
- Each todo renders in a row (data-testid="todo-item") showing its text (data-testid="todo-text").
- An empty list shows a friendly empty-state message (data-testid="empty-list") instead of nothing.
- A checkbox per row toggles completed; completed todos render with a strikethrough.
- An Edit button turns a row's text into an editable input, with a Save button to commit the change.
- A Delete button removes only that specific todo.
- Each todo gets a stable unique id on creation — never use array index as the key.
Signature
function TodoList(): JSX.Element
Example
<TodoList />
// type "Buy milk", click Add ⇒ a new row appears with that text
// click its checkbox ⇒ text gets a strikethrough
// click Edit, change text, Save ⇒ row updates
// click Delete ⇒ row disappears
Constraints
- Use only useState — no useReducer or Context needed for this one.
- Do not use array index as the id/key for todos.