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
checkedbound 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.