Eine Todo-App mit React bauen
Zeit für ein echtes Projekt: In diesem Tutorial baust du Schritt für Schritt eine Todo-App mit React und setzt State, Listen und Formulare zusammen.
Jetzt wird es praktisch: Wir bauen gemeinsam eine kleine Todo-App. Dabei wendest du alles an, was du bisher gelernt hast – State, Listen, Formulare und Events. Am Ende hast du eine funktionierende App, in der du Aufgaben hinzufügen, abhaken und löschen kannst. Lass uns loslegen.
Das Grundgerüst anlegen
Wir starten mit einer Komponente, die den State für unsere Aufgaben hält. Jede Aufgabe ist ein Objekt mit einer ID, einem Text und einem Status:
import { useState } from "react";
function TodoApp() {
const [todos, setTodos] = useState([]);
const [text, setText] = useState("");
return (
<div>
<h1>Meine Aufgaben</h1>
</div>
);
}
export default TodoApp;Das Array todos speichert alle Aufgaben, text hält die aktuelle Eingabe.
Aufgaben hinzufügen
Wir brauchen ein Formular und eine Funktion, die eine neue Aufgabe ans Array anhängt. Wichtig: Wir erzeugen immer ein neues Array mit dem Spread-Operator:
function hinzufuegen(e) {
e.preventDefault();
if (text.trim() === "") return;
const neueAufgabe = { id: Date.now(), text, erledigt: false };
setTodos([...todos, neueAufgabe]);
setText("");
}Mit Date.now() erzeugen wir eine einfache, eindeutige ID. Die Prüfung auf text.trim() verhindert leere Einträge.
Die Liste anzeigen
Jetzt rendern wir die Aufgaben mit map. Jeder Eintrag bekommt seinen key aus der ID:
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<span
style={{
textDecoration: todo.erledigt ? "line-through" : "none",
}}
>
{todo.text}
</span>
</li>
))}
</ul>Ist eine Aufgabe erledigt, zeigen wir sie durchgestrichen an. Der Status steuert also direkt die Darstellung.
Aufgaben abhaken und löschen
Zum Abhaken erstellen wir eine Funktion, die den Status der passenden Aufgabe umkehrt. Auch hier verändern wir das alte Array nicht direkt, sondern erzeugen mit map ein neues:
function umschalten(id) {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, erledigt: !todo.erledigt } : todo
)
);
}
function loeschen(id) {
setTodos(todos.filter((todo) => todo.id !== id));
}Beim Löschen nutzen wir filter, um alle Aufgaben außer der gewählten zu behalten. Beide Funktionen folgen demselben Prinzip: nie mutieren, immer neu erzeugen.
Alles zusammensetzen
Hier ist die vollständige Komponente mit Formular, Liste und Buttons:
function TodoApp() {
const [todos, setTodos] = useState([]);
const [text, setText] = useState("");
function hinzufuegen(e) {
e.preventDefault();
if (text.trim() === "") return;
setTodos([...todos, { id: Date.now(), text, erledigt: false }]);
setText("");
}
function umschalten(id) {
setTodos(
todos.map((t) =>
t.id === id ? { ...t, erledigt: !t.erledigt } : t
)
);
}
function loeschen(id) {
setTodos(todos.filter((t) => t.id !== id));
}
return (
<div>
<h1>Meine Aufgaben</h1>
<form onSubmit={hinzufuegen}>
<input value={text} onChange={(e) => setText(e.target.value)} />
<button>Hinzufügen</button>
</form>
<ul>
{todos.map((t) => (
<li key={t.id}>
<span onClick={() => umschalten(t.id)}>{t.text}</span>
<button onClick={() => loeschen(t.id)}>X</button>
</li>
))}
</ul>
</div>
);
}Fazit
Glückwunsch – du hast eine vollständige Todo-App gebaut! Du hast gesehen, wie State, Listen und Formulare zusammenspielen und wie wichtig es ist, Arrays mit map und filter unveränderlich zu behandeln. Von hier aus kannst du die App beliebig erweitern: Speichern im localStorage, Filter für erledigte Aufgaben oder ein hübscheres Design. Du hast jetzt das Rüstzeug, um eigene React-Projekte zu starten.