Zum Inhalt springen
React Anfänger 25 min

Listen rendern

Lerne, wie du Arrays von Daten in React als Listen renderst. Verstehe das key-Attribut und verschiedene Rendering-Patterns.

Aktualisiert:

Listen rendern

In fast jeder App musst du Listen von Daten anzeigen – Produkte, Benutzer, Nachrichten oder Todos. React macht das mit der map()-Methode aus JavaScript elegant und einfach.

Grundlagen: Arrays mit map() rendern

Die map()-Methode verwandelt jedes Element eines Arrays in ein JSX-Element:

function FruitList() {
  const fruits = ['Apfel', 'Banane', 'Kirsche', 'Dattel', 'Erdbeere'];

  return (
    <ul>
      {fruits.map((fruit, index) => (
        <li key={index}>{fruit}</li>
      ))}
    </ul>
  );
}

Wie es funktioniert

// 1. Du hast ein Array
const fruits = ['Apfel', 'Banane', 'Kirsche'];

// 2. map() verwandelt jedes Element
fruits.map((fruit, index) => <li key={index}>{fruit}</li>);

// 3. Das Ergebnis ist ein Array von JSX-Elementen:
// [<li>Apfel</li>, <li>Banane</li>, <li>Kirsche</li>]

// 4. React rendert dieses Array automatisch

Das key-Attribut

Jedes Element in einer Liste braucht ein eindeutiges key-Attribut. React nutzt Keys, um Elemente effizient zu aktualisieren.

Warum Keys wichtig sind

// SCHLECHT - Index als Key (nur als Notloesung)
{items.map((item, index) => (
  <li key={index}>{item}</li>
))}

// GUT - Eindeutige ID als Key
{items.map(item => (
  <li key={item.id}>{item.name}</li>
))}

Regeln fuer Keys

RegelBeispiel
Eindeutig unter GeschwisternKeine doppelten Keys in derselben Liste
StabilAendert sich nicht zwischen Renders
Nicht Index (wenn moeglich)IDs aus der Datenbank verwenden
// Datenbank-IDs sind ideal
const users = [
  { id: 'u1', name: 'Max' },
  { id: 'u2', name: 'Anna' },
  { id: 'u3', name: 'Tom' }
];

function UserList() {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Wann Index als Key okay ist

Der Index als Key ist akzeptabel, wenn:

  • Die Liste sich nie aendert (kein Sortieren, Filtern, Loeschen)
  • Die Elemente keinen eigenen State haben
  • Die Liste nicht neu sortiert wird

Objekt-Arrays rendern

In der Praxis arbeitest du meistens mit Arrays von Objekten:

function ProductList() {
  const products = [
    { id: 1, name: 'Laptop', price: 999.99, inStock: true },
    { id: 2, name: 'Maus', price: 29.99, inStock: true },
    { id: 3, name: 'Tastatur', price: 79.99, inStock: false },
    { id: 4, name: 'Monitor', price: 449.99, inStock: true }
  ];

  return (
    <div>
      <h2>Unsere Produkte</h2>
      {products.map(product => (
        <div key={product.id} style={{
          padding: '1rem',
          borderBottom: '1px solid #eee',
          opacity: product.inStock ? 1 : 0.5
        }}>
          <h3>{product.name}</h3>
          <p>{product.price.toFixed(2)} Euro</p>
          <span>{product.inStock ? 'Verfuegbar' : 'Ausverkauft'}</span>
        </div>
      ))}
    </div>
  );
}

Listen mit Komponenten

Lagere die Listenelemente in eigene Komponenten aus:

function TodoItem({ todo, onToggle }) {
  return (
    <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      padding: '0.5rem',
      borderBottom: '1px solid #eee'
    }}>
      <input
        type="checkbox"
        checked={todo.done}
        onChange={() => onToggle(todo.id)}
      />
      <span style={{
        textDecoration: todo.done ? 'line-through' : 'none',
        color: todo.done ? '#999' : '#333'
      }}>
        {todo.text}
      </span>
    </div>
  );
}

function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: 'React lernen', done: false },
    { id: 2, text: 'Projekt bauen', done: false },
    { id: 3, text: 'Deployen', done: false }
  ]);

  function handleToggle(id) {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, done: !todo.done } : todo
    ));
  }

  return (
    <div>
      <h2>Meine Todos</h2>
      {todos.map(todo => (
        <TodoItem key={todo.id} todo={todo} onToggle={handleToggle} />
      ))}
    </div>
  );
}

Listen filtern

Kombiniere filter() mit map():

function FilteredUserList() {
  const users = [
    { id: 1, name: 'Max', role: 'admin', active: true },
    { id: 2, name: 'Anna', role: 'user', active: true },
    { id: 3, name: 'Tom', role: 'user', active: false },
    { id: 4, name: 'Lisa', role: 'admin', active: true }
  ];

  const [filter, setFilter] = useState('all');

  const filteredUsers = users.filter(user => {
    if (filter === 'admin') return user.role === 'admin';
    if (filter === 'active') return user.active;
    return true; // 'all'
  });

  return (
    <div>
      <div style={{ marginBottom: '1rem' }}>
        <button onClick={() => setFilter('all')}>Alle</button>
        <button onClick={() => setFilter('admin')}>Admins</button>
        <button onClick={() => setFilter('active')}>Aktive</button>
      </div>

      {filteredUsers.length > 0 ? (
        <ul>
          {filteredUsers.map(user => (
            <li key={user.id}>
              {user.name} ({user.role})
              {!user.active && ' - Inaktiv'}
            </li>
          ))}
        </ul>
      ) : (
        <p>Keine Benutzer gefunden.</p>
      )}

      <p>{filteredUsers.length} Ergebnis(se)</p>
    </div>
  );
}

Listen sortieren

function SortableList() {
  const [sortBy, setSortBy] = useState('name');
  const [sortOrder, setSortOrder] = useState('asc');

  const items = [
    { id: 1, name: 'Banane', price: 1.29 },
    { id: 2, name: 'Apfel', price: 0.99 },
    { id: 3, name: 'Kirsche', price: 3.49 },
    { id: 4, name: 'Dattel', price: 5.99 }
  ];

  const sortedItems = [...items].sort((a, b) => {
    let comparison = 0;
    if (sortBy === 'name') {
      comparison = a.name.localeCompare(b.name);
    } else {
      comparison = a.price - b.price;
    }
    return sortOrder === 'asc' ? comparison : -comparison;
  });

  return (
    <div>
      <div>
        <button onClick={() => setSortBy('name')}>Nach Name</button>
        <button onClick={() => setSortBy('price')}>Nach Preis</button>
        <button onClick={() => setSortOrder(o => o === 'asc' ? 'desc' : 'asc')}>
          {sortOrder === 'asc' ? 'Aufsteigend' : 'Absteigend'}
        </button>
      </div>

      <ul>
        {sortedItems.map(item => (
          <li key={item.id}>
            {item.name} - {item.price.toFixed(2)} Euro
          </li>
        ))}
      </ul>
    </div>
  );
}

Leere Listen behandeln

Zeige immer einen sinnvollen Zustand, wenn die Liste leer ist:

function MessageList({ messages }) {
  if (messages.length === 0) {
    return (
      <div style={{ textAlign: 'center', padding: '2rem', color: '#999' }}>
        <p>Keine Nachrichten vorhanden.</p>
        <p>Schreibe deine erste Nachricht!</p>
      </div>
    );
  }

  return (
    <div>
      {messages.map(msg => (
        <div key={msg.id} style={{ padding: '0.5rem', borderBottom: '1px solid #eee' }}>
          <strong>{msg.author}:</strong> {msg.text}
        </div>
      ))}
    </div>
  );
}

Verschachtelte Listen

function CategoryList() {
  const categories = [
    {
      id: 'c1',
      name: 'Frontend',
      technologies: ['React', 'Vue', 'Angular', 'Svelte']
    },
    {
      id: 'c2',
      name: 'Backend',
      technologies: ['Node.js', 'Python', 'Java', 'Go']
    },
    {
      id: 'c3',
      name: 'Datenbank',
      technologies: ['PostgreSQL', 'MongoDB', 'Redis']
    }
  ];

  return (
    <div>
      {categories.map(category => (
        <div key={category.id} style={{ marginBottom: '1rem' }}>
          <h3>{category.name}</h3>
          <ul>
            {category.technologies.map(tech => (
              <li key={tech}>{tech}</li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  );
}

Uebungen

  1. Rendere eine Kontaktliste mit Name, E-Mail und Telefonnummer aus einem Array von Objekten
  2. Baue eine filterbare Filmliste mit Genres als Filterbuttons
  3. Erstelle eine sortierbare Tabelle mit Spalten fuer Name, Alter und Stadt

Was kommt als Naechstes?

Du kannst jetzt Listen in React rendern. Im naechsten Kapitel lernst du den useState Hook kennen – damit kannst du interaktiven State in deinen Komponenten verwalten und deine App wirklich dynamisch machen.

Zusammenfassung

  • Nutze map() um Arrays in JSX-Elemente umzuwandeln
  • Jedes Listenelement braucht ein eindeutiges key-Attribut
  • Verwende Datenbank-IDs als Keys, nicht den Array-Index
  • Kombiniere filter() und sort() mit map() fuer dynamische Listen
  • Behandle immer den leeren Zustand einer Liste
  • Lagere Listenelemente in eigene Komponenten aus

Pro-Tipp: Erstelle nie den Key waehrend des Renderns mit Math.random() oder Date.now() – das erzeugt bei jedem Render neue Keys und zerstoert die Performance-Vorteile. Keys muessen stabil und vorhersagbar sein!

Zurück zum React Kurs