Build a Mini Task List App

Site Admin · 11 Sep 2026 · 11 views

Build a Mini Task List App

Put everything together with a small but complete task list. You will use state, events, lists, and keys in one component.

The data model

Each task is an object with an id, a text, and a done flag. The initial list is empty, and new tasks are added through a form.

App component

function App() {
  const [tasks, setTasks] = useState([]);
  const [text, setText] = useState('');

  function addTask() {
    const task = { id: Date.now(), text, done: false };
    setTasks([...tasks, task]);
    setText('');
  }

  function toggleDone(id) {
    setTasks(tasks.map((t) =>
      t.id === id ? { ...t, done: !t.done } : t
    ));
  }

  return (
    <div>
      <input value={text}
        onChange={(e) => setText(e.target.value)} />
      <button onClick={addTask}>Add</button>
      <ul>
        {tasks.map((t) => (
          <li key={t.id}
            onClick={() => toggleDone(t.id)}
            style={{ textDecoration: t.done ? 'line-through' : 'none' }}>
            {t.text}
          </li>
        ))}
      </ul>
    </div>
  );
}

How it works

Typing updates text through the onChange handler. Clicking Add creates a task object, appends it to the state array, and clears the input. Clicking a task flips its done flag. The map call renders every item with the id as the key, so updates stay stable.

Extending it

Add a delete button that filters the array, or a counter that filters by done status. Every improvement reuses the same tools: state for data, events for input, and map for rendering.

Key Points

  • Combine useState with forms to capture input.
  • Build new arrays instead of mutating state.
  • Render lists with map and unique keys.
  • Use spread syntax for immutable updates.
  • Extend the app by composing more state and events.
Share this post:

Comments (0)

Please login or register to comment.