Optionen:
Komponentennamen beginnen immer mit einem Großbuchstaben
(um sie von gewöhnlichen HTML-Elementen zu unterscheiden)
Komponenten werden üblicherweise als default export in seperaten Dateien definiert
// TodoItem.tsx
export default function TodoItem() {
// ...
}
Komponenten haben oft eine zugehörige Stil-Datei
// TodoItem.tsx
import './TodoItem.css';
Elternkomponenten können Daten aus ihrem State via Props an Unterkomponenten weitergeben (unidirektionaler Datenfluss)
Wenn wir State und Props einer Komponente kennen, wissen wir ziemlich genau, wie sie dargestellt wird
Wenn mehrere Komponenten auf den gleichen State zugreifen können sollen:
der State wird in einer gemeinsamen übergeordneten Komponente gespeichert und wird via Props nach unten übergeben
(siehe: React docs: sharing state between components)
Oft wird der Großteil des States in der obersten Komponente gespeichert (z.B. in App
)
Unterkomponenten können Events auslösen, die dazu führen, dass sich der State in der Elternkomponente ändert
Beispiel:
<Rating value={prodRating} />
Props werden an Funktionskomponenten mittels eines props-Parameters übergeben:
type Props = { value: number };
function Rating(props: Props) {
// we can access "props.value"
}
alternative Notation mit Destrukturierung:
type Props = { value: number };
function Rating({ value }: Props) {
// we can access "value" directly
}
Implementierung einer Rating-Komponente:
type Props = { value: number };
function Rating({ value }: Props) {
const starIds = [1, 2, 3, 4, 5];
return (
<div className="Rating">
{starIds.map((id) => (
<span key={id}>{id <= value ? '★' : '☆'}</span>
))}
</div>
);
}
Ãœbung: Erstelle eine ProgressBar-Komponente:
<ProgressBar percentage={75} color="lightgreen" />
Beispiel mit einem "Slot":
<Notification type="error">
<h1>Error</h1>
<p>Changes could not be saved</p>
</Notification>
Beispiel mit zwei benannten "Slots":
<Notification
type="error"
header={<h1>Error</h1>}
body={<p>Changes could not be saved</p>}
/>
diese Notationen sind gleichwertig:
<Notification type="error">
<div>foo</div>
</Notification>
<Notification type="error" children={<div>foo</div>} />
was zwischen den öffnenden und schließenden Tags übergeben wird, wird als props.children
erhalten
Implementierung einer Notification
Komponente:
type Props = {
type: 'info' | 'warning' | 'error';
children: ReactNode;
};
function Notification({ type, children }: Props) {
return (
<div className={`Notification Notification--${type}`}>
{children}
</div>
);
}
Übung: Card-Komponente mit Styling (Beispiel für ein Resultat mit CSS-Deklarationen)
<Card>
<h1>heading</h1>
<p>content</p>
</Card>
Aufgabe: In der Todo-Anwendung: Extrahiere eine Statistics
-Komponente, die z.B. die folgenden Informationen anzeigt:
5 todos (3 incomplete, 2 completed)
mögliche einfache Dateistruktur:
Aufgabe: Erstelle einfache wiederverwendbare Komponenten, die hauptsächlich für Styling verwendet werden
Beispiele:
AppBar
(Beispiele: MUI, react-bootstrap)Alert
(Beispiele: MUI, react-bootstrap)Avatar
or LetterAvatar
(Beispiel: MUI)List
und ListItem
(Beispiel: MUI)Diese Komponenten sollten keine Interaktivität haben (keine Events)
Props:
Eine Komponente (z.B. App) kann Daten (aus dem eigenen State) an eine Unterkomponente (z.B. Rating) übergeben
Events:
Eine Unterkomponente kann ein Event auslösen, wodurch sich dann State in einer drüberliegenden Komponente ändert
Eventhandler werden als Funktionen definiert und via props übergeben / erhalten.
Eventnamen beginnen üblicherweise mit on
, z.B. onChange
, onClose
, ...
Beispiel:
<Rating
value={prodRating}
onChange={(newRating) => setProdRating(newRating)}
/>
Beispiel für Prop-Types einer Rating-Komponente:
type Props = {
value: number;
onChange?: (value: number) => void;
};
function Rating({ value, onChange }: Props) {
const starIds = [1, 2, 3, 4, 5];
return (
<div className="Rating">
{starIds.map((id) => (
<span
onClick={() => {
if (onChange) {
onChange(id);
}
}}
key={id}
>
{id <= value ? '★' : '☆'}
</span>
))}
</div>
);
}
Verwendung einer Rating-Komponente:
const [prodRating, setProdRating] = useState(3);
<Rating
value={prodRating}
onChange={(newRating) => setProdRating(newRating)}
/>
Aufgabe: Erstelle wiederverwendbare interaktive Komponenten (mit etwas Styling)
Beispiele:
Button
(Beispiele: MUI, react-bootstrap)TextInput
(Beispiele: MUI, react-bootstrap)Pagination
(Beispiele: MUI, react-bootstrap)Aufgabe: Teile die Todo-Anwendung in kleinere Komponenten, die mittels Props und Events kommunizieren (z.B. AddTodo, TodoItem, TodoList)
Aufgabe: Entwirf die Struktur von Props, Events und State für verschiedene Komponenten (z.B. Calendar, ColorPicker, BarChart, Tabs)