How to Create a Todo App in React: Simple Step-by-Step Guide
To create a todo app in React, use functional components with the
useState hook to manage the list of tasks and input state. Render the tasks as a list and update the state when adding or removing todos.Syntax
A basic todo app in React uses a functional component with useState to hold the list of todos and the current input value. You create functions to add new todos and remove existing ones. The component returns JSX that renders an input box, a button, and a list of todos.
useState: React hook to hold and update state.onChange: Event handler to update input value.onClick: Event handler to add a todo.map(): To render each todo item.
jsx
import React, { useState } from 'react'; function TodoApp() { const [todos, setTodos] = useState([]); // List of todo items const [input, setInput] = useState(''); // Current input value const addTodo = () => { if (input.trim() === '') return; // Ignore empty input setTodos([...todos, input.trim()]); setInput(''); }; const removeTodo = (index) => { setTodos(todos.filter((_, i) => i !== index)); }; return ( <div> <input value={input} onChange={e => setInput(e.target.value)} placeholder="Add todo" /> <button onClick={addTodo}>Add</button> <ul> {todos.map((todo, i) => ( <li key={i}> {todo} <button onClick={() => removeTodo(i)}>Remove</button> </li> ))} </ul> </div> ); } export default TodoApp;
Output
A webpage showing an input box with placeholder 'Add todo', an 'Add' button, and below it a list of todos with each having a 'Remove' button.
Example
This example shows a complete React todo app where you can type a task, click 'Add' to add it to the list, and remove tasks by clicking 'Remove'. It uses functional components and hooks for state.
jsx
import React, { useState } from 'react'; import ReactDOM from 'react-dom/client'; function TodoApp() { const [todos, setTodos] = useState([]); const [input, setInput] = useState(''); const addTodo = () => { if (input.trim() === '') return; setTodos([...todos, input.trim()]); setInput(''); }; const removeTodo = (index) => { setTodos(todos.filter((_, i) => i !== index)); }; return ( <main style={{ fontFamily: 'Arial, sans-serif', maxWidth: '400px', margin: '2rem auto' }}> <h1>Todo App</h1> <input type="text" value={input} onChange={e => setInput(e.target.value)} placeholder="Add todo" aria-label="Todo input" style={{ padding: '0.5rem', width: '70%' }} /> <button onClick={addTodo} style={{ padding: '0.5rem', marginLeft: '0.5rem' }}>Add</button> <ul style={{ listStyle: 'none', padding: 0, marginTop: '1rem' }}> {todos.map((todo, i) => ( <li key={i} style={{ marginBottom: '0.5rem' }}> <strong>{todo}</strong> <button onClick={() => removeTodo(i)} aria-label={`Remove ${todo}`} style={{ marginLeft: '1rem' }} > Remove </button> </li> ))} </ul> </main> ); } const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<TodoApp />);
Output
A clean webpage titled 'Todo App' with an input box and 'Add' button on top, and below a list of added todos each with a 'Remove' button to delete them.
Common Pitfalls
Common mistakes when creating a todo app in React include:
- Not using
useStateproperly, causing the UI not to update. - Mutating the state array directly instead of creating a new array.
- Not handling empty input, which adds blank todos.
- Missing
keyprop in list items, causing rendering issues.
Always create new arrays when updating state and validate input before adding.
jsx
/* Wrong: Mutating state directly */ const addTodoWrong = () => { todos.push(input); // This mutates state directly setTodos(todos); // React may not detect change }; /* Right: Create new array */ const addTodoRight = () => { setTodos([...todos, input]); };
Quick Reference
Tips for building a React todo app:
- Use
useStateto hold todos and input. - Update state immutably with new arrays.
- Use
map()to render lists with uniquekeyprops. - Validate input to avoid empty todos.
- Use semantic HTML and accessible labels.
Key Takeaways
Use React functional components with the useState hook to manage todo list and input state.
Always update state immutably by creating new arrays instead of modifying existing ones.
Render todos with map() and provide unique keys to list items for proper React rendering.
Validate input to prevent adding empty todos and improve user experience.
Add accessible labels and semantic HTML for better usability and accessibility.