Skip to main content

Todo List (Basic)

Difficulty: Core

Problem Statement​

Render todos and toggle complete/incomplete using checkbox.

Live Demo​

Try the running app below β€” this is the target behavior for the challenge.

Todo List (Basic) β€” Live Demo
  • Learn React state
  • Build transfer list

What Interviewers Expect​

  • Immutable todo updates.
  • Checkbox checked bound to todo state.
  • Visual completed state (line-through).

Step-by-Step Implementation​

Step 1 β€” Todo state array​

Each todo has id, title, done flag.

const [todos, setTodos] = useState([{ id: 1, title: '...', done: false }]);

Step 2 β€” Toggle handler​

Map and flip only matching todo.

setTodos((prev) => prev.map((t) => t.id === id ? { ...t, done: !t.done } : t));

Complete Implementation​

Copy-paste ready single-file solution. Use this as your reference after attempting the challenge yourself, or paste it into CodeSandbox / StackBlitz to run locally.

App.jsx
import React, {useState} from 'react';

export default function App() {
const [todos, setTodos] = useState([
{id: 1, title: 'Learn React state', done: false},
{id: 2, title: 'Build transfer list', done: false},
]);

const toggle = (id) => {
setTodos((prev) =>
prev.map((todo) => (todo.id === id ? {...todo, done: !todo.done} : todo)),
);
};

return (
<ul style={{listStyle: 'none', padding: 0}}>
{todos.map((todo) => (
<li key={todo.id} style={{display: 'flex', gap: '0.5rem', marginBottom: '0.35rem'}}>
<input type="checkbox" checked={todo.done} onChange={() => toggle(todo.id)} />
<span style={{textDecoration: todo.done ? 'line-through' : 'none'}}>{todo.title}</span>
</li>
))}
</ul>
);
}

Final Checklist​

  • UI works for primary flow
  • Edge cases handled (empty/disabled/loading where relevant)
  • State updates are immutable
  • Components are readable and reasonably split
  • You can explain trade-offs out loud in an interview

Next Challenge​

Continue to the next item in the sidebar when you're comfortable implementing this from scratch in 30–45 minutes.