Zum Inhalt springen
React Anfänger 25 min

Children & Komposition

Lerne das Children-Pattern in React kennen und verstehe, wie du flexible, wiederverwendbare Komponenten durch Komposition baust.

Aktualisiert:

Children & Komposition

Die children-Prop ist eines der maechtigsten Konzepte in React. Sie erlaubt es dir, Inhalte zwischen die Tags einer Komponente zu schreiben – genau wie bei HTML-Elementen. Zusammen mit Komposition baust du damit extrem flexible UIs.

Was ist die children-Prop?

Wenn du eine Komponente mit oeffnendem und schliessendem Tag verwendest, wird alles dazwischen als children-Prop uebergeben:

// Der Text zwischen den Tags ist "children"
<Button>Klick mich</Button>

// In der Komponente:
function Button({ children }) {
  return (
    <button style={{ padding: '8px 16px' }}>
      {children}
    </button>
  );
}

Einfache Children-Beispiele

Text als Children

function Highlight({ children }) {
  return (
    <span style={{
      backgroundColor: '#ffeaa7',
      padding: '2px 6px',
      borderRadius: '4px'
    }}>
      {children}
    </span>
  );
}

// Verwendung
<p>Das ist ein <Highlight>wichtiger</Highlight> Text.</p>

JSX als Children

function Card({ children }) {
  return (
    <div style={{
      border: '1px solid #ddd',
      borderRadius: '12px',
      padding: '1.5rem',
      boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
    }}>
      {children}
    </div>
  );
}

// Verwendung - beliebiger Inhalt!
<Card>
  <h2>Mein Titel</h2>
  <p>Mein Text hier drin.</p>
  <button>Aktion</button>
</Card>

Komponenten als Children

<Card>
  <Avatar name="Max" />
  <UserInfo name="Max" role="Admin" />
</Card>

Wrapper-Komponenten

Ein haeufiges Pattern: Wrapper-Komponenten, die Layout oder Styling bereitstellen:

function PageLayout({ children }) {
  return (
    <div style={{
      maxWidth: '1200px',
      margin: '0 auto',
      padding: '2rem'
    }}>
      {children}
    </div>
  );
}

function Section({ title, children }) {
  return (
    <section style={{ marginBottom: '2rem' }}>
      <h2 style={{ borderBottom: '2px solid #3498db', paddingBottom: '0.5rem' }}>
        {title}
      </h2>
      {children}
    </section>
  );
}

// Verwendung
function AboutPage() {
  return (
    <PageLayout>
      <h1>Ueber uns</h1>
      <Section title="Unsere Mission">
        <p>Wir machen das Programmierenlernen einfach.</p>
      </Section>
      <Section title="Unser Team">
        <p>Ein Team von begeisterten Entwicklern.</p>
      </Section>
    </PageLayout>
  );
}

Komposition vs. Vererbung

React bevorzugt Komposition ueber Vererbung. Statt spezielle Komponenten durch Vererbung zu erstellen, nutzt du Komposition:

// Allgemeine Dialog-Komponente
function Dialog({ children }) {
  return (
    <div style={{
      position: 'fixed',
      top: '50%',
      left: '50%',
      transform: 'translate(-50%, -50%)',
      backgroundColor: 'white',
      padding: '2rem',
      borderRadius: '12px',
      boxShadow: '0 4px 20px rgba(0,0,0,0.3)',
      minWidth: '300px'
    }}>
      {children}
    </div>
  );
}

// Spezialisierte Dialoge durch Komposition
function ConfirmDialog({ title, message, onConfirm, onCancel }) {
  return (
    <Dialog>
      <h2>{title}</h2>
      <p>{message}</p>
      <div style={{ display: 'flex', gap: '1rem', justifyContent: 'flex-end' }}>
        <button onClick={onCancel}>Abbrechen</button>
        <button onClick={onConfirm} style={{
          backgroundColor: '#e74c3c', color: 'white',
          border: 'none', padding: '8px 16px', borderRadius: '4px'
        }}>
          Bestaetigen
        </button>
      </div>
    </Dialog>
  );
}

function SuccessDialog({ message, onClose }) {
  return (
    <Dialog>
      <h2 style={{ color: '#27ae60' }}>Erfolg!</h2>
      <p>{message}</p>
      <button onClick={onClose}>Schliessen</button>
    </Dialog>
  );
}

Mehrere Slots mit benannten Props

Manchmal brauchst du mehrere “Slots” fuer Inhalte. Nutze dafuer benannte Props:

function Layout({ header, sidebar, children, footer }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '250px 1fr', minHeight: '100vh' }}>
      <header style={{ gridColumn: '1 / -1', padding: '1rem', background: '#2c3e50', color: 'white' }}>
        {header}
      </header>
      <aside style={{ padding: '1rem', background: '#ecf0f1' }}>
        {sidebar}
      </aside>
      <main style={{ padding: '1rem' }}>
        {children}
      </main>
      <footer style={{ gridColumn: '1 / -1', padding: '1rem', background: '#34495e', color: 'white' }}>
        {footer}
      </footer>
    </div>
  );
}

// Verwendung
function App() {
  return (
    <Layout
      header={<h1>Meine App</h1>}
      sidebar={
        <nav>
          <a href="/">Home</a>
          <a href="/about">Ueber uns</a>
        </nav>
      }
      footer={<p>2026 Meine App</p>}
    >
      <h2>Willkommen!</h2>
      <p>Das ist der Hauptinhalt.</p>
    </Layout>
  );
}

Bedingte Children

Du kannst pruefen, ob Children vorhanden sind:

function Container({ title, children }) {
  return (
    <div style={{ border: '1px solid #ddd', borderRadius: '8px' }}>
      {title && (
        <div style={{ padding: '1rem', borderBottom: '1px solid #ddd' }}>
          <h3 style={{ margin: 0 }}>{title}</h3>
        </div>
      )}
      <div style={{ padding: '1rem' }}>
        {children || <p style={{ color: '#999' }}>Kein Inhalt vorhanden.</p>}
      </div>
    </div>
  );
}

// Mit Inhalt
<Container title="Nachrichten">
  <p>Du hast 5 neue Nachrichten.</p>
</Container>

// Ohne Inhalt
<Container title="Benachrichtigungen" />

Praktisches Beispiel: UI-Komponenten-Bibliothek

Lass uns eine kleine Sammlung wiederverwendbarer Komponenten bauen:

// Alert-Komponente
function Alert({ variant = 'info', children }) {
  const colors = {
    info: { bg: '#d4edda', border: '#c3e6cb', text: '#155724' },
    warning: { bg: '#fff3cd', border: '#ffeeba', text: '#856404' },
    error: { bg: '#f8d7da', border: '#f5c6cb', text: '#721c24' }
  };

  const style = colors[variant];

  return (
    <div style={{
      padding: '1rem',
      borderRadius: '8px',
      backgroundColor: style.bg,
      border: `1px solid ${style.border}`,
      color: style.text,
      marginBottom: '1rem'
    }}>
      {children}
    </div>
  );
}

// Badge-Komponente
function Badge({ children, color = '#3498db' }) {
  return (
    <span style={{
      display: 'inline-block',
      padding: '2px 8px',
      borderRadius: '12px',
      backgroundColor: color,
      color: 'white',
      fontSize: '0.8rem'
    }}>
      {children}
    </span>
  );
}

// Tooltip-Komponente
function Tooltip({ text, children }) {
  return (
    <span style={{ position: 'relative', cursor: 'help' }} title={text}>
      {children}
      <span style={{
        borderBottom: '1px dashed currentColor'
      }} />
    </span>
  );
}

// Alles zusammen
function App() {
  return (
    <PageLayout>
      <Alert variant="info">
        <strong>Tipp:</strong> Willkommen in unserer App!
      </Alert>

      <Alert variant="warning">
        Dein Passwort laeuft in <Badge color="#e67e22">3 Tagen</Badge> ab.
      </Alert>

      <p>
        Lerne mehr ueber{' '}
        <Tooltip text="Eine JavaScript-Bibliothek fuer UIs">
          React
        </Tooltip>
        .
      </p>
    </PageLayout>
  );
}

Children manipulieren

React stellt Hilfsfunktionen bereit, um mit Children zu arbeiten:

import { Children, cloneElement } from 'react';

function ButtonGroup({ children }) {
  return (
    <div style={{ display: 'flex', gap: '0.5rem' }}>
      {Children.map(children, (child, index) =>
        cloneElement(child, {
          style: {
            ...child.props.style,
            borderRadius: index === 0 ? '8px 0 0 8px' :
                          index === Children.count(children) - 1 ? '0 8px 8px 0' : '0'
          }
        })
      )}
    </div>
  );
}

// Verwendung
<ButtonGroup>
  <button>Links</button>
  <button>Mitte</button>
  <button>Rechts</button>
</ButtonGroup>

Uebungen

  1. Erstelle eine Modal-Komponente mit Header, Body (children) und Footer-Slots
  2. Baue eine Accordion-Komponente, die mehrere AccordionItem-Children annimmt
  3. Erstelle eine Tabs-Komponente mit verschiedenen Tab-Panels als Children

Was kommt als Naechstes?

Du verstehst jetzt Children und Komposition. Im naechsten Kapitel lernst du, wie du Listen rendern kannst – ein haeufiges Pattern in React-Anwendungen, bei dem du Arrays von Daten in UI-Elemente verwandelst.

Zusammenfassung

  • Children ist eine spezielle Prop fuer Inhalte zwischen den Tags einer Komponente
  • Komposition ist das bevorzugte Pattern in React – statt Vererbung
  • Wrapper-Komponenten stellen Layout und Styling bereit
  • Fuer mehrere Slots nutze benannte Props neben children
  • Children koennen Text, JSX oder andere Komponenten sein
  • Mit Children.map() und cloneElement() kannst du Children manipulieren

Pro-Tipp: Bevorzuge Komposition gegenueber komplexen Props. Statt einer Komponente mit 20 Props zu erstellen, baue lieber mehrere kleinere Komponenten, die du flexibel zusammensetzen kannst. Das macht deinen Code lesbarer und wartbarer!

Zurück zum React Kurs