Skip to content

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:

  1. Eltern übergibt eine Funktion als Prop (onSend)
  2. Kind ruft diese Funktion auf
  3. 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

SzenarioLösung
Eltern → KindProps
Kind → ElternCallback-Funktion (Props)
GeschwisterShared State (Lifting State Up)
Überspringen von EbenenuseContext
Globaler StateuseReducer + 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

Frei für alle Anfänger