Combine components, state, events and lists.
This small app uses everything from the tutorial:
Components with props
useState for the todo list and the input
Controlled form with onSubmit
Rendering a list with keys
Updating and filtering arrays immutably
Try extending it: add an "edit" button, a filter (all / active / done), or save todos in localStorage with useEffect.
💡 Key Takeaways: React Mini Project: Todo App
Mastering React Mini Project: Todo App helps you write clean and reliable React code. Follow standard conventions, test edge cases, and keep logic simple. Try running the code example below and complete the exercises to build confidence.
React Mini Project: Todo App Code Example
React
<div id="root"></div>
<script src="https://unpkg.com/react@18.3.1/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone@7.25.6/babel.min.js"></script>
<script type="text/babel">
const { useState, useEffect, useRef, useMemo, createContext, useContext } = React;
function TodoItem({ todo, onToggle, onDelete }) {
return (
<li style={{ display: "flex", gap: 8, alignItems: "center", padding: "4px 0" }}>
<input type="checkbox" checked={todo.done} onChange={() => onToggle(todo.id)} />
<span style={{ flex: 1, textDecoration: todo.done ? "line-through" : "none" }}>{todo.text}</span>
<button onClick={() => onDelete(todo.id)}>✕</button>
</li>
);
}
function App() {
const [todos, setTodos] = useState([
{ id: 1, text: "Learn JSX", done: true },
{ id: 2, text: "Practise hooks", done: false },
]);
const [text, setText] = useState("");
const add = (e) => {
e.preventDefault();
if (!text.trim()) return;
setTodos([...todos, { id: Date.now(), text, done: false }]);
setText("");
};
const toggle = (id) => setTodos(todos.map(t => t.id === id ? { ...t, done: !t.done } : t));
const remove = (id) => setTodos(todos.filter(t => t.id !== id));
const left = todos.filter(t => !t.done).length;
return (
<div style={{ maxWidth: 360, fontFamily: "sans-serif" }}>
<h2>My Todos ({left} left)</h2>
<form onSubmit={add}>
<input value={text} onChange={e => setText(e.target.value)} placeholder="New todo" />
<button>Add</button>
</form>
<ul style={{ listStyle: "none", padding: 0 }}>
{todos.map(t => <TodoItem key={t.id} todo={t} onToggle={toggle} onDelete={remove} />)}
</ul>
</div>
);
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
</script>
Free sign-in required · Google login available
Stuck on something?
Ask the community in the CodesInTech forum.
Need a developer?
Learning on your own is great — and when you need professional help, our team builds custom software, websites and mobile apps for clients worldwide.
Explore Our Services