Children & Komposition
Lerne das Children-Pattern in React kennen und verstehe, wie du flexible, wiederverwendbare Komponenten durch Komposition baust.
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
- Erstelle eine
Modal-Komponente mit Header, Body (children) und Footer-Slots - Baue eine
Accordion-Komponente, die mehrereAccordionItem-Children annimmt - 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()undcloneElement()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!