Diese Notiz behandelt den Einsatz von Schleifen zur dynamischen Darstellung von Komponenten in React. Im Fokus steht die Nutzung von Array-Methoden wie .map(), um wiederholende UI-Strukturen effizient zu erzeugen. Zusätzlich wird auf den Umgang mit eindeutigen key-Props sowie auf bewährte Muster zur sauberen und wartbaren Implementierung eingegangen.
Einfaches Beispiel
Wenn man bestimmte Arrays oder sonstige Sequenz-Strukturen durchlaufen möchte, kann man in JSX direkt diese Listen-Objekte durchlaufen.
const ArrayExample = () => {
const names = ['John', 'Tom', 'Henry'];
return (
<ul>
{names.map(name => (
<li>{name}</li>
))}
</ul>
);
};
export default ArrayExample;Die Elemente werden klassisch im Browser als gerendert.

Schleifen und Schlüssel (Key)
Wenn man beim vorherigen Beispiel in die Konsole des Browser einen Blick wirft, wird man feststellen, dass React eine Warnung generiert, die wie folgt aussieht.

Wichtiger Punkt: Für eine reibungslose Aktualisierung von Elementen wird eindringlich empfohlen ein key Attribut einzusetzen, damit React die einzelne Elemente eindeutig und korrekt zuordnen kann.
const ArrayExample = () => {
const names = ['John', 'Tom', 'Henry'];
return (
<ul>
{names.map((name, idx) => (
<li key={idx}>{name}</li>
))}
</ul>
);
};
export default ArrayExample;Dynamische Daten und Schlüssel
Die Verwendung von Index als Schlüssel ist bei statischen Listen in Ordnung. Bei dynamischen Listen, in denen Elemente hinzugefügt werden, entfernt oder neu angeordnet werden, sollte man eindeutige IDs verwenden.
const ArrayExample = () => {
const persons = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Tom', },
{ id: 3, name: 'Henry' }
];
return (
<ul>
{persons.map(person => (
<li key={person.id}>{person.name}</li>
))}
</ul>
);
};
export default ArrayExample;Wenn man Listen hat, die keine direkte Möglichkeit bieten, etwas als ein Index zu verwenden, kann man auch diese Indexe generieren. Hier soll nur lediglich darauf geachtet werden, dass diese Indexe eindeutig sind.
Im folgenden Beispiel wird die Math.random() verwendet. Die Werte, welche diese Funktion generiert, können allerdings sich wiederholen. Daher sollte man, um wirklich eindeutige Werte zu erhalten ggf. die Verwendung von Math.random() mit anderen Mittel kombinieren. In diesem Fall wird lediglich eine mögliche Verwendung gezeigt.
const ArrayExample = () => {
const items = [100, 200, 300, 400, 500];
return (
<ul>
{items.map(item => (
<li key={Math.floor(Math.random() * 100)}>{item}</li>
))}
</ul>
);
};
export default ArrayExample;Im obigen Beispiel generieren wir für jedes Element eine Zufallszahl zwischen 0 und 100. Wobei die generierten Werte, wie bereits angesprochen, sich wiederholen können.
Um wirklich eindeutige Werte zu erhalten, könnte man Zeitstempel mit einbeziehen.
const ArrayExample = () => {
const items = [100, 200, 300, 400, 500];
return (
<ul>
{items.map(item => (
<li key={new Date().getTime() * (Math.random() * 10)}>{item}</li>
))}
</ul>
);
};
export default ArrayExample;Warum Keys wirklich wichtig sind
Keys sind nicht „nur" eine Konvention zum Ruhigstellen der React-Konsole. Sie sind das Mittel, mit dem React entscheidet, welches alte UI-Element zu welchem neuen UI-Element gehört. Dieser Vorgang heißt Reconciliation.
Was passiert ohne stabile Keys?
Stell dir folgende Liste vor, die per Drag-and-Drop umgeordnet wird:
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo, idx) => (
<li key={idx}>
<input type="checkbox" defaultChecked={todo.done} />
{todo.text}
</li>
))}
</ul>
);
}Wird ein Eintrag entfernt, verschieben sich alle Indizes. React denkt: „Der Eintrag mit key=2 ist immer noch da" – obwohl es ein anderer ist. Lokaler State der Listen-Items wird falsch zugeordnet, etwa der Checkbox-Zustand. Das ist eine der häufigsten Bug-Quellen in React-Listen.
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<input type="checkbox" defaultChecked={todo.done} />
{todo.text}
</li>
))}
</ul>
);
}Wann ist index als Key in Ordnung?
In genau einem Szenario: die Liste verändert sich nie (statisch) oder nur am Ende (kein Insert/Reorder/Delete in der Mitte) und Listen-Items haben keinen eigenen lokalen State.
Anforderungen an einen Key
- Eindeutig unter den Geschwistern (nicht in der ganzen App).
- Stabil zwischen Renders – derselbe logische Eintrag bekommt immer denselben Key.
- Keine Zufallszahl zur Render-Zeit.
key={Math.random()}zerstört bei jedem Render die Zuordnung – React unmounted und remounted alle Items, was teuer ist und State löscht.
Keys generieren, wenn keine vorhanden sind
Hast du Daten ohne IDs, generiere Keys einmalig beim Erzeugen der Daten (z. B. mit crypto.randomUUID() oder einer monoton steigenden Zähler-ID), nicht während des Renderns.
function addTodo(text) {
setTodos((current) => [
...current,
{ id: crypto.randomUUID(), text, done: false },
]);
}So bleibt die ID über Re-Renders stabil und eignet sich als Key.
Entpacken von Eigenschaften
Wenn man über Objekte iteriert, die ein entsprechendes Set an Eigenschaften haben, muss in der Regel jede Eigenschaft des Objektes über das jeweilige Objekt angesprochen werden.
const persons = [
{ name: 'John', age: 30, job: 'Developer' },
{ name: 'Tom', age: 25, job: 'Manager' },
{ name: 'Henry', age: 34, job: 'Designer' }
];
persons.forEach(person => {
// Name
console.log(person.name);
// Job
console.log(person.job);
});
Man kann etwas an Schreibarbeit sparen, wenn man die Eigenschaften des Objektes entpackt. Im reinen JavaScript würde es folgendermaßen aussehen.
const persons = [
{ name: 'John', age: 30, job: 'Developer' },
{ name: 'Tom', age: 25, job: 'Manager' },
{ name: 'Henry', age: 34, job: 'Designer' }
];
persons.forEach(({ name, age, job }) => {
// Name
console.log(person.name);
// Job
console.log(person.job);
});
Diese Technik kann ebenfalls in React Components eingesetzt werden. Hier soll allerdings darauf geachtet werden, dass die Lesbarkeit des Codes und die Offensichtlichkeit bestimmter Kontexte nicht leidet. Wenn man ein größeres Konstrukt hat und zu Beginn der Schleife die Destruktion durchführt, weiß man weiter unten ggf. nicht immer zu welchem Objekt eine Eigenschaft gehört.
const ArrayExample = () => {
const persons = [
{ name: 'John', age: 30, job: 'Developer' },
{ name: 'Tom', age: 25, job: 'Manager' },
{ name: 'Henry', age: 34, job: 'Designer' }
];
return (
<ul>
{persons.map(({ name, age, job }, idx) => (
<li key={idx}>Name: {name}<br/> Age: {age}<br/> Job: {job}</li>
))}
</ul>
);
};
export default ArrayExample;
Aufbau von Elementen innerhalb JavaScript
Es besteht auch die Möglichkeit JSX-Elemente direkt innerhalb von JavaScript aufzubauen. Gemeint ist damit, dass wir innerhalb einer Funktion, beispielsweise, problemlos Bestandteile eines Templates in JSX zusammenbauen können.
Stellen wir uns ein einfaches Component vor. Wir definieren dort eine Variable, welche ein Array ist und bestimmte Elemente aufnehmen kann.
const Sample = () => {
const items = [];
for (let i = 0; i < 5; i++) {
items.push((
<li>{i + 1}</li>
));
}
return (
<ul>
{items}
</ul>
);
};
export default Sample;Wie man sehen kann, kriegen wir eine reguläre Ausgabe. Das Array mit li Elementen wird korrekt und automatisch entpackt.

Häufige Stolperfallen
key={Math.random()} ist die teuerste Falle.
Bei jedem Render ein neuer Key. React kann keine Verbindung zwischen den Renders mehr ziehen — jedes Element wird komplett unmounted und remounted. Lokaler State (Checkbox-Zustand, Input-Wert, Focus) geht verloren. Außerdem viel Performance-Overhead.
Index als Key bei dynamischen Listen — Zustands-Bug.
Wird ein Element aus der Mitte entfernt, verschieben sich alle Indizes nach vorn. React denkt: „Key 2 ist immer noch da" — aber der Inhalt hat sich geändert. Lokaler Item-State (z.B. Checkbox, Form-Input) bleibt am alten Index, gehört aber jetzt zu einem anderen logischen Datensatz.
key ist auf der mappten Komponente, nicht auf children.
arr.map(x => <Foo><Bar key={x.id} /></Foo>) ist falsch — der Key gehört auf das DIREKT von map zurückgegebene Element (<Foo key={x.id}>...</Foo>). React warnt im Dev-Mode bei fehlendem Key dort.
forEach statt map liefert kein Array — nichts rendert.
arr.forEach hat keinen Rückgabewert. {arr.forEach(x => <li>...</li>)} rendert nichts. map liefert ein neues Array zurück und das wird gerendert.
React rendert Arrays mit JSX-Children automatisch.
{arr.map(...)} rendert alle Elemente. Man muss NICHT manuell mit .join('') oder ähnlichem arbeiten. React kennt Arrays als Children und entpackt sie selbst.
Keys sind nur unter Geschwistern eindeutig nötig, nicht global.
Zwei Listen können denselben Key gleichzeitig haben — solange jeder Key in seiner Geschwister-Gruppe eindeutig ist. Daher: Index als Key innerhalb einer kleinen statischen Liste ist okay, auch wenn zehn andere Listen auf der Seite ihre eigenen Index-Keys haben.
crypto.randomUUID() einmalig beim Erstellen, nicht im Render.
UUIDs sind perfekte Keys — aber MUSS einmal beim Anlegen des Datensatzes generiert und dann mitgespeichert werden. id: crypto.randomUUID() im map-Callback zerstört genauso wie Math.random() die Stabilität.
Fragment mit Key — die spezielle Schreibweise.
Wenn map ein Fragment zurückgibt und dort ein Key hin soll, geht die Kurzform <></> nicht — sie hat keine Props. Die Langform <React.Fragment key={...}></React.Fragment> ist nötig.
Weiterführende Ressourcen
Externe Quellen
- Rendering Lists – react.dev
- Keeping List Items in Order with
key– react.dev - Preserving and Resetting State – react.dev
- crypto.randomUUID() – MDN