useState Hook
Meistere den useState Hook - den wichtigsten Hook in React. Lerne, wie du interaktiven State in deinen Komponenten verwaltest.
useState Hook
Der useState-Hook ist der wichtigste Hook in React. Er gibt deinen Komponenten ein Gedaechtnis – sie koennen sich Werte merken und die Anzeige aktualisieren, wenn sich diese Werte aendern.
Was ist State?
State ist der veraenderliche Zustand einer Komponente. Waehrend Props von aussen kommen und nicht veraendert werden duerfen, gehoert State der Komponente selbst:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Zaehler: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
useState verstehen
Die Syntax
const [stateVariable, setterFunction] = useState(initialValue);
stateVariable– der aktuelle WertsetterFunction– die Funktion zum Aktualisieren des WertsinitialValue– der Anfangswert
Schritt fuer Schritt
import { useState } from 'react';
function NameInput() {
// 1. State deklarieren mit Anfangswert ''
const [name, setName] = useState('');
// 2. State in JSX verwenden
// 3. State mit Setter aktualisieren
return (
<div>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Dein Name"
/>
<p>Hallo, {name || 'Fremder'}!</p>
</div>
);
}
Verschiedene State-Typen
Zahlen
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Plus</button>
<button onClick={() => setCount(count - 1)}>Minus</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
Strings
function TextEditor() {
const [text, setText] = useState('');
return (
<div>
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
rows={5}
cols={40}
/>
<p>Zeichen: {text.length}</p>
</div>
);
}
Booleans
function ToggleSwitch() {
const [isOn, setIsOn] = useState(false);
return (
<div>
<button onClick={() => setIsOn(!isOn)}>
{isOn ? 'AN' : 'AUS'}
</button>
<p>Der Schalter ist {isOn ? 'eingeschaltet' : 'ausgeschaltet'}.</p>
</div>
);
}
Arrays
function TodoList() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
function addTodo() {
if (input.trim()) {
setTodos([...todos, { id: Date.now(), text: input, done: false }]);
setInput('');
}
}
function removeTodo(id) {
setTodos(todos.filter(todo => todo.id !== id));
}
function toggleTodo(id) {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, done: !todo.done } : todo
));
}
return (
<div>
<div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && addTodo()}
placeholder="Neues Todo..."
/>
<button onClick={addTodo}>Hinzufuegen</button>
</div>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<span
onClick={() => toggleTodo(todo.id)}
style={{
textDecoration: todo.done ? 'line-through' : 'none',
cursor: 'pointer'
}}
>
{todo.text}
</span>
<button onClick={() => removeTodo(todo.id)}>X</button>
</li>
))}
</ul>
</div>
);
}
Objekte
function UserForm() {
const [user, setUser] = useState({
name: '',
email: '',
age: ''
});
function handleChange(field, value) {
setUser({ ...user, [field]: value });
}
return (
<form>
<input
placeholder="Name"
value={user.name}
onChange={(e) => handleChange('name', e.target.value)}
/>
<input
placeholder="E-Mail"
value={user.email}
onChange={(e) => handleChange('email', e.target.value)}
/>
<input
placeholder="Alter"
type="number"
value={user.age}
onChange={(e) => handleChange('age', e.target.value)}
/>
<pre>{JSON.stringify(user, null, 2)}</pre>
</form>
);
}
State richtig aktualisieren
Wichtig: Niemals State direkt aendern!
// FALSCH - State direkt aendern
const [user, setUser] = useState({ name: 'Max', age: 25 });
user.name = 'Anna'; // Niemals machen!
// RICHTIG - Neues Objekt erstellen
setUser({ ...user, name: 'Anna' });
// FALSCH - Array direkt aendern
const [items, setItems] = useState([1, 2, 3]);
items.push(4); // Niemals machen!
// RICHTIG - Neues Array erstellen
setItems([...items, 4]);
Array-Operationen mit State
| Operation | Falsch (mutiert) | Richtig (neues Array) |
|---|---|---|
| Hinzufuegen | arr.push(item) | [...arr, item] |
| Entfernen | arr.splice(i, 1) | arr.filter(...) |
| Aendern | arr[i] = newVal | arr.map(...) |
| Sortieren | arr.sort() | [...arr].sort() |
Updater-Funktionen
Wenn der neue State vom vorherigen abhaengt, nutze eine Updater-Funktion:
function Counter() {
const [count, setCount] = useState(0);
function incrementThree() {
// FALSCH - count ist in allen drei Aufrufen derselbe Wert
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
// Ergebnis: count + 1 (nicht + 3!)
// RICHTIG - Updater-Funktion bekommt den aktuellsten Wert
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// Ergebnis: count + 3
}
return (
<div>
<p>{count}</p>
<button onClick={incrementThree}>+3</button>
</div>
);
}
Mehrere State-Variablen
Du kannst useState mehrfach verwenden:
function SignupForm() {
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [agreeToTerms, setAgreeToTerms] = useState(false);
const isValid = username.length >= 3 &&
email.includes('@') &&
password.length >= 8 &&
agreeToTerms;
return (
<form>
<input
placeholder="Benutzername (min. 3 Zeichen)"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<input
type="email"
placeholder="E-Mail"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Passwort (min. 8 Zeichen)"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<label>
<input
type="checkbox"
checked={agreeToTerms}
onChange={(e) => setAgreeToTerms(e.target.checked)}
/>
Ich stimme den AGB zu
</label>
<button disabled={!isValid}>Registrieren</button>
</form>
);
}
Lazy Initialization
Wenn der Anfangswert teuer zu berechnen ist, uebergib eine Funktion:
// SCHLECHT - wird bei JEDEM Render aufgerufen
const [data, setData] = useState(expensiveCalculation());
// GUT - wird nur beim ERSTEN Render aufgerufen
const [data, setData] = useState(() => expensiveCalculation());
// Praktisches Beispiel: LocalStorage lesen
const [theme, setTheme] = useState(() => {
return localStorage.getItem('theme') || 'light';
});
Uebungen
- Baue einen Zaehler mit Plus, Minus und Reset-Buttons
- Erstelle ein Formular mit mehreren Feldern und Live-Vorschau
- Baue eine Einkaufsliste mit Hinzufuegen, Loeschen und Abhaken von Eintraegen
Was kommt als Naechstes?
Du beherrschst jetzt useState – der Grundstein fuer interaktive React-Apps. Im naechsten Kapitel lernst du Event Handling im Detail kennen – wie du auf Klicks, Tastendruecke und andere Benutzeraktionen reagierst.
Zusammenfassung
useStategibt Komponenten ein Gedaechtnis fuer veraenderliche Werte- Die Syntax ist
const [value, setValue] = useState(initialValue) - Niemals State direkt aendern – immer den Setter verwenden
- Fuer Objekte und Arrays immer neue Kopien erstellen (Spread-Operator)
- Nutze Updater-Funktionen wenn der neue State vom vorherigen abhaengt
- Lazy Initialization spart Performance bei teuren Berechnungen
Pro-Tipp: Halte deinen State so minimal wie moeglich. Wenn du einen Wert aus vorhandenem State berechnen kannst (z.B. filteredItems aus items und filter), dann speichere ihn nicht als separaten State – berechne ihn stattdessen bei jedem Render. Weniger State bedeutet weniger Bugs!