// projects.react
10 Best React JS Projects
Hand-picked and ordered easiest → hardest — each with complete code and expected output. Build these to turn lessons into a portfolio.
Back to React JS course
// solution.code
react
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
// Main Todo App Component
function TodoApp() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
// Load todos from localStorage on mount
useEffect(() => {
const saved = localStorage.getItem('todos');
if (saved) setTodos(JSON.parse(saved));
}, []);
// Save todos to localStorage whenever they change
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);
// Add new todo
const addTodo = () => {
if (input.trim()) {
setTodos([...todos, { id: Date.now(), text: input, completed: false }]);
setInput('');
}
};
// Toggle todo completion
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
// Delete todo
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
return (
<div style={{ padding: '20px', maxWidth: '500px', margin: '0 auto' }}>
<h1>Todo List</h1>
<div style={{ marginBottom: '20px' }}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && addTodo()}
placeholder="Add a new todo..."
style={{ padding: '8px', width: '70%' }}
/>
<button onClick={addTodo} style={{ padding: '8px 16px', marginLeft: '10px' }}>Add</button>
</div>
<ul style={{ listStyle: 'none', padding: 0 }}>
{todos.map(todo => (
<li key={todo.id} style={{ marginBottom: '10px', display: 'flex', alignItems: 'center' }}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span style={{
marginLeft: '10px',
textDecoration: todo.completed ? 'line-through' : 'none',
flex: 1
}}>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)} style={{ padding: '4px 8px' }}>Delete</button>
</li>
))}
</ul>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<TodoApp />); output
A functional todo list interface is displayed with an input field and Add button at the top. Users can add todos by typing and clicking Add or pressing Enter. Each todo item shows a checkbox (to toggle completion with strikethrough effect), the todo text, and a Delete button. All data persists in browser localStorage, so refreshing the page maintains the todo list state.
