Project 1
Unlike the chapter challenges, this is a project brief, not a graded exercise — there's no single correct solution file. Instead, you get requirements, a suggested structure, and stretch goals; how you actually build it is up to you. A todo list might seem simple, but it touches almost every Fundamentals concept at once: state, lists, conditional rendering, controlled inputs, and component composition, all working together in one small app.
Requirements
- A text input and "Add" button for entering a new todo — pressing Enter should also work, not just clicking the button.
- Each todo displays its text and has a way to mark it complete (e.g. a checkbox) and a way to delete it.
- Completed todos should look visually distinct from incomplete ones (e.g. strikethrough text, dimmed color).
- The input should clear itself after a todo is successfully added.
- Adding an empty/blank todo should be prevented.
- If the list is empty, show a friendly message (e.g. "No todos yet — add one above!") instead of an empty list.
Suggested Component Breakdown
This isn't the only valid structure — it's a starting point. The key decision worth sticking to: the array of todos itself should live in TodoApp (the lowest common ancestor of the form and the list), with TodoForm and TodoItem each receiving only the props and callbacks they specifically need, exactly as covered in Fundamentals Chapter 10.
A Reasonable Build Order
- Get a static version working first — hardcode a small array of 2–3 todo objects (
{ id, text, completed }) and render them withTodoList/TodoItembefore wiring up any state changes. - Move that array into
useStateinTodoApp, so it's now real state instead of a hardcoded constant. - Wire up
TodoFormto add a new todo object to the array on submit, generating a uniqueidfor each one (e.g.Date.now()is a quick option for a small project like this). - Add the "toggle complete" behavior — clicking a todo's checkbox should flip its
completedvalue without affecting any other todo in the array. - Add the delete behavior — removing exactly one todo from the array by its
id, leaving the rest unchanged. - Add the empty-state message and the blank-input guard last, once the core add/toggle/delete flow is solid.
- Add an "edit" mode — double-clicking a todo's text turns it into an editable input.
- Add filter buttons (All / Active / Completed) above the list.
- Show a live count of remaining (incomplete) todos.
- Persist the list to
localStorageso it survives a page refresh (a preview of Intermediate Chapter 6's data-handling patterns). - Add a "Clear completed" button that removes every completed todo at once.