Appearance
Kapitel 9: Komponenten-Kommunikation
In React ist Datenfluss in der Regel von oben nach unten (Eltern → Kinder). Um Daten zwischen Komponenten auszutauschen, benötigen wir verschiedene Techniken.
9.1 Eltern zu Kind (Props)
📤 Daten senden
Elternkomponente:
jsx
function App() {
const message = "Hallo Kind!";
return (
<div>
<Child text={message} />
</div>
);
}📥 Daten empfangen
Kindkomponente:
jsx
function Child(props) {
return <h1>{props.text}</h1>;
}
// Oder mit Destrukturierung
function Child({ text }) {
return <h1>{text}</h1>;
}9.2 Kind zu Eltern (Callback-Funktion)
📝 Funktions-Props verwenden
Elternkomponente:
jsx
function App() {
const [message, setMessage] = useState("");
const handleChildData = (data) => {
setMessage(data);
};
return (
<div>
<p>Nachricht vom Kind: {message}</p>
<Child onSend={handleChildData} />
</div>
);
}Kindkomponente:
jsx
function Child({ onSend }) {
const sendData = () => {
onSend("Hallo von Kind!");
};
return <button onClick={sendData}>Senden</button>;
}Ablauf:
- Eltern übergibt eine Funktion als Prop (
onSend) - Kind ruft diese Funktion auf
- Daten werden an die Eltern übergeben
9.3 Geschwister-Kommunikation (Shared State)
🎯 Gemeinsamer State in Elternkomponente
Problem: Zwei Geschwister-Komponenten müssen Daten austauschen.
Lösung: State in die gemeinsame Elternkomponente heben (Lifting State Up).
jsx
function App() {
const [data, setData] = useState("");
return (
<div>
<SiblingA onDataChange={setData} />
<SiblingB data={data} />
</div>
);
}
function SiblingA({ onDataChange }) {
return <input onChange={(e) => onDataChange(e.target.value)} />;
}
function SiblingB({ data }) {
return <p>Empfangen: {data}</p>;
}9.4 Überspringen von Ebenen (useContext)
🤔 Wann useContext verwenden?
Wenn Daten an viele Komponenten weitergegeben werden müssen, ohne Props durch jede Ebene zu reichen (Props-Drilling).
📦 Context erstellen
jsx
import { createContext, useContext } from 'react';
// 1. Context erstellen
const UserContext = createContext();🏠 Provider bereitstellen
jsx
function App() {
const user = { name: "Max", age: 25 };
return (
<UserContext.Provider value={user}>
<Header />
</UserContext.Provider>
);
}📥 Context verwenden
jsx
function Header() {
const user = useContext(UserContext);
return <h1>Willkommen, {user.name}!</h1>;
}Vorteile:
- Kein Props-Drilling
- Daten global verfügbar
Nachteile:
- Kann Performance beeinträchtigen, wenn zu häufig verwendet
9.5 Globale Zustandsverwaltung (useReducer + useContext)
📦 useReducer Grundlagen
useReducer ist eine Alternative zu useState für komplexe Zustandslogik.
jsx
import { useReducer } from 'react';
// Reducer-Funktion
function counterReducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(counterReducer, { count: 0 });
return (
<div>
<p>Zähler: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}🌐 Globaler State mit useReducer + useContext
Schritt 1: Store erstellen
jsx
import { createContext, useContext, useReducer } from 'react';
const StoreContext = createContext();
const initialState = {
user: null,
isLoggedIn: false
};
function storeReducer(state, action) {
switch (action.type) {
case 'LOGIN':
return { ...state, user: action.payload, isLoggedIn: true };
case 'LOGOUT':
return { ...state, user: null, isLoggedIn: false };
default:
return state;
}
}
function StoreProvider({ children }) {
const [state, dispatch] = useReducer(storeReducer, initialState);
return (
<StoreContext.Provider value={{ state, dispatch }}>
{children}
</StoreContext.Provider>
);
}Schritt 2: Provider in App verwenden
jsx
function App() {
return (
<StoreProvider>
<Header />
<Main />
</StoreProvider>
);
}Schritt 3: State in Komponenten verwenden
jsx
function Header() {
const { state, dispatch } = useContext(StoreContext);
return (
<div>
{state.isLoggedIn ? (
<>
<p>Willkommen, {state.user.name}!</p>
<button onClick={() => dispatch({ type: 'LOGOUT' })}>Logout</button>
</>
) : (
<button onClick={() => dispatch({ type: 'LOGIN', payload: { name: 'Max' } })}>
Login
</button>
)}
</div>
);
}9.6 Kommunikations-Szenarien Zusammenfassung
| Szenario | Lösung |
|---|---|
| Eltern → Kind | Props |
| Kind → Eltern | Callback-Funktion (Props) |
| Geschwister | Shared State (Lifting State Up) |
| Überspringen von Ebenen | useContext |
| Globaler State | useReducer + useContext (oder Redux) |
📝 Zusammenfassung
In diesem Kapitel haben wir gelernt:
- ✅ Daten von Eltern zu Kind (Props)
- ✅ Daten von Kind zu Eltern (Callback-Funktion)
- ✅ Geschwister-Kommunikation (Shared State)
- ✅ useContext für übersprungene Ebenen
- ✅ Globaler Zustand mit useReducer + useContext
🎯 Nächste Schritte
Im nächsten Kapitel werden wir lernen:
- React Router für Navigation
- Single Page Application (SPA) Konzept
- Verschlüsselte Routen und Dynamische Routen
Bereit für Routing? → Kapitel 10: React Router
