Build Lab / Project
Build a task tracker with explicit state
Implement add and complete operations without mutating prior state. Use the checks as project milestones.
You will learn to
- Define a small state transition contract
- Reject empty titles
- Preserve previous state while updating one task
Before you start
Basic programming and the introductory activities
Model the smallest useful state
A task is an object with id, title and done. State is an array of tasks. applyTasks receives the old array and an action, then returns a new array. There is no database and no login in this project. The value of the exercise is making update behavior predictable before adding a user interface or persistence.
Milestone one: add
For an add action, trim the title. An empty or whitespace-only title leaves state unchanged. Use the supplied id so tests can reproduce results. Reject a duplicate id by leaving state unchanged. A new task starts with done false. Use array spreading or concat rather than pushing into the caller’s array.
Milestone two: complete
For a complete action, return an array where the matching task is copied with done true. Other tasks stay unchanged. Completing a missing id should leave the data unchanged, and completing an already-complete task should not create duplicates. An unknown action is a no-op.
Milestone three: test before extending
The checks cover addition, empty input, completion, duplicates and mutation. Print the initial and final arrays to see the transition. After passing, extend your function with a rename action and write a check for a blank new title. Browser checks are learning feedback, not a production authorization system.
Try it yourself
function applyTasks(tasks, action) {
// Implement add and complete. Do not mutate tasks.
return tasks;
}
console.log(applyTasks([], {type:"add",id:1,title:" First task "}));Enable JavaScript for this interactive activity. You can read all lesson explanations above without it.