Zwei der wichtigsten Konzepte in React – State und Props – werden gerne verwechselt. Beide halten Daten, beide lösen Re-Renders aus, beide werden in Komponenten genutzt. Trotzdem haben sie unterschiedliche Aufgaben und unterschiedliche Eigenschaften. Dieser Artikel erklärt den Unterschied, zeigt typische Verwechslungen und gibt klare Regeln, wann Daten in den State gehören und wann sie als Prop gereicht werden sollten.

Die Kernunterschiede in einem Bild

EigenschaftStateProps
Wer besitzt die Daten?Die Komponente selbstDie Eltern-Komponente
Wer darf sie ändern?Nur die besitzende KomponenteNiemand (read-only innerhalb Kind)
Reicht weiter nach unten?Optional, über PropsJa, von Eltern zu Kind
InitialisierunguseState(initialValue)Beim JSX-Aufruf gesetzt
AnwendungVeränderliche, lokale WerteDaten, die von außen kommen
Auslöser für Re-RendersetState-AufrufGeänderte Prop vom Eltern-Render

Kurz: Props kommen von außen rein, State entsteht innen.

Beispiel-Komponente mit beidem

TypeScript Greeting.jsx
import { useState } from 'react';

function Greeting({ name }) {
    const [greeted, setGreeted] = useState(false);

    return (
        <div>
            <h1>Hallo, {name}!</h1>
            {!greeted && (
                <button onClick={() => setGreeted(true)}>
                    Begrüßung bestätigen
                </button>
            )}
            {greeted && <p>Schön, dich zu sehen.</p>}
        </div>
    );
}
  • name ist eine Prop – kommt von außen, wird im Kind nicht verändert.
  • greeted ist State – gehört zur Komponente, wird per Klick verändert.

Props sind read-only

Eine Komponente darf ihre Props nicht direkt verändern. Das ist eine harte Regel von React – Verstöße führen zu schwer auffindbaren Bugs, weil die Eltern-Komponente die Daten weiter besitzt und in einem späteren Render möglicherweise einen anderen Wert erwartet.

TypeScript − Niemals direkt eine Prop verändern
function Counter({ count }) {
    count++; // − Prop wird mutiert
    return <p>{count}</p>;
}

Soll der Wert sich ändern können, muss er in den State (entweder lokal oder im Eltern-Component, der die Prop reicht). Mehr dazu unter State Lifting.

Drei Faustregeln zur Entscheidung

Wenn unklar ist, ob ein Wert State oder Prop sein soll, frage in dieser Reihenfolge:

  1. Bleibt der Wert über die Zeit gleich? -> Konstante. Weder State noch Prop, sondern eine normale Variable oder Konstante.
  2. Bekommt die Komponente den Wert von außen? -> Prop.
  3. Kann sich der Wert über die Zeit ändern, und keine andere Komponente besitzt ihn? -> State.

Wenn der Wert sich aus anderen Werten berechnen lässt, gehört er weder in State noch in Props – er wird beim Rendern abgeleitet:

TypeScript + Abgeleitete Werte einfach berechnen
function Cart({ items }) {
    const total = items.reduce((sum, item) => sum + item.price, 0);
    return <p>Gesamt: {total} €</p>;
}

total darf weder State noch Prop sein – es ist eine reine Funktion von items.

State und Props zusammen

Häufig leitet ein Eltern-Komponente seinen State an Kinder weiter. Aus Sicht des Eltern ist es State, aus Sicht des Kindes ist es eine Prop. Das ist der Kern des einseitigen Datenflusses:

TypeScript Parent + Child
function Counter() {
    const [count, setCount] = useState(0); // State im Parent

    return (
        <div>
            <Display value={count} />
            <button onClick={() => setCount(count + 1)}>+1</button>
        </div>
    );
}

function Display({ value }) {
    // Aus Sicht von Display ist value eine Prop
    return <p>{value}</p>;
}

Display weiß nicht, woher der Wert kommt – ob aus State, aus einem Context oder aus einem Server-Request. Genau das macht es wiederverwendbar.

Anti-Pattern: Prop in State spiegeln

Ein häufiger Fehler: Eine Prop wird beim Mounten in einen State kopiert, um sie „bearbeitbar" zu machen.

TypeScript − Anti-Pattern
function Form({ initialName }) {
    const [name, setName] = useState(initialName);
    // Problem: Wenn sich initialName ändert, bleibt name auf altem Wert.
    return <input value={name} onChange={(e) => setName(e.target.value)} />;
}

Das funktioniert für den ersten Render – aber wenn der Eltern-Komponent eine neue initialName-Prop liefert, bleibt der State auf dem alten Wert hängen. Bessere Optionen:

  • Prop direkt verwenden, falls keine Bearbeitung nötig ist.
  • Den State im Eltern-Komponent halten und Setter als Prop reichen.
  • Per key-Prop den State bewusst zurücksetzen, wenn die Identität wechselt.
TypeScript + key zwingt State-Reset
// Wenn userId wechselt, wird der gesamte State von Form weggeworfen
<Form key={userId} initialName={userName} />

Was passiert beim Re-Render?

  • State-Update (setX(...)) führt dazu, dass die Komponente und ihre Kinder neu gerendert werden.
  • Prop-Änderung führt dazu, dass die empfangende Komponente neu gerendert wird.

In beiden Fällen baut React den virtuellen Baum neu auf und vergleicht ihn mit dem alten. Das heißt: Sobald State irgendwo oben wechselt, rendern alle abhängigen Komponenten – das ist das normale, gewünschte Verhalten. Performance-Stellschrauben dafür: React.memo, useMemo, useCallback.

Interessantes

State ist intern, Props sind extern — eine Sache der Perspektive.

Was in Komponente A State ist, kann in Komponente B als Prop ankommen — wenn B ein Kind von A ist und A den Wert weiterreicht. Daher: State und Props sind nicht zwei Arten von Werten, sondern zwei Rollen desselben Werts.

Props sind read-only — eine harte Regel.

Wer in der Kind-Komponente props.value = 5 schreibt, hat einen Bug. React erwartet, dass Props immutable sind. Wenn das Kind den Wert ändern können soll, gehört ein Callback-Prop mit (z.B. onChange), den das Kind aufruft.

State lebt im React-internen Speicher, nicht in der Komponenten-Funktion.

Bei jedem Render läuft die Komponenten-Funktion neu — aber useState liest den Wert aus dem internen Speicher, nicht aus der Funktion. Deshalb überlebt State zwischen Renders, obwohl die Funktion neu ausgeführt wird.

Props können sich zwischen Renders ändern — State im Initializer nicht.

Wer initialen State aus Props ableitet (useState(props.value)), bekommt den Wert NUR beim ersten Mount. Ändern sich Props später, hat das keinen Einfluss. Lösung: useEffect mit Props in Dependencies, oder key-Prop für Re-Mount.

Doppelter State ist ein Anti-Pattern — Single Source of Truth.

Wenn dieselbe Information in zwei States/Props existiert, kann sie auseinanderlaufen. Faustregel: Daten an EINER Stelle halten, von dort an alle Konsumenten propagieren — entweder via Props oder Context.

State Lifting ist die Antwort auf 'wo gehört der State hin?'

Wenn zwei Geschwister-Komponenten denselben Wert brauchen: in den gemeinsamen Eltern lifen. Wenn drei tief verschachtelte Komponenten denselben Wert brauchen: noch höher lifen, oder Context nutzen.

Boolean-Props mit isXyz, hasXyz, canXyz benennen.

Naming-Konvention: isOpen, hasError, canSubmit. Macht beim Lesen sofort klar, dass es eine boolean Prop ist. Setter analog: setIsOpen.

Bei React.memo: Props-Vergleich per Reference-Identity.

React.memo(Child) rendert nur neu, wenn sich Props per Object.is-Vergleich ändern. Daher: bei Objekt/Array/Funktion-Props auf Reference-Stabilität achten — sonst memo ist wirkungslos.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu State

Zur Übersicht