Komponentendefinition

Komponentendefinition

Optionen:

  • Definieren einer Komponente als Funktion
  • Definieren einer Komponente als Klasse (etwas veraltet)

Komponentendefinition

Komponentennamen beginnen immer mit einem Großbuchstaben

(um sie von gewöhnlichen HTML-Elementen zu unterscheiden)

Komponentendefinition

Komponenten werden üblicherweise als default export in seperaten Dateien definiert

// TodoItem.tsx

export default function TodoItem() {
  // ...
}

Komponentendefinition

Komponenten haben oft eine zugehörige Stil-Datei

// TodoItem.tsx

import './TodoItem.css';

Props und Events

State und Props

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

Beispiel: Komponenten und Props in einer Todo-Anwendung

image/svg+xml TodoItem TodoItem todo TodoList TodoApp todos AddTodo newTitle ... todos todo Statistics todos

State über mehrere Komponenten hinweg teilen

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)

Events

Unterkomponenten können Events auslösen, die dazu führen, dass sich der State in der Elternkomponente ändert

Beispiel: Komponenten und Events in einer Todo-Anwendung

image/svg+xml TodoItem TodoItem onDelete onCompletedChange TodoList TodoApp todos AddTodo newTitle ... Statistics onAdd onDelete onCompletedChange onDelete onCompletedChange

Komponenten-Props

Komponenten-Props

Beispiel:

<Rating value={prodRating} />

Komponenten-Props

Props werden an Funktionskomponenten mittels eines props-Parameters übergeben:

type Props = { value: number };

function Rating(props: Props) {
  // we can access "props.value"
}

Komponenten-Props

alternative Notation mit Destrukturierung:

type Props = { value: number };

function Rating({ value }: Props) {
  // we can access "value" directly
}

Komponenten-Props

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>
  );
}

Komponenten-Props

Ãœbung: Erstelle eine ProgressBar-Komponente:

<ProgressBar percentage={75} color="lightgreen" />

Inhalte an Komponenten übergeben

Inhalte an Komponenten übergeben

Beispiel mit einem "Slot":

<Notification type="error">
  <h1>Error</h1>
  <p>Changes could not be saved</p>
</Notification>

Inhalte an Komponenten übergeben

Beispiel mit zwei benannten "Slots":

<Notification
  type="error"
  header={<h1>Error</h1>}
  body={<p>Changes could not be saved</p>}
/>

Inhalte an Komponenten übergeben

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

Inhalte an Komponenten übergeben

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>
  );
}

Inhalte an Komponenten übergeben

Übung: Card-Komponente mit Styling (Beispiel für ein Resultat mit CSS-Deklarationen)

<Card>
  <h1>heading</h1>
  <p>content</p>
</Card>

Ãœbungen

Ãœbungen

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:

  • index.tsx
  • App.tsx
  • App.css
  • components
    • Statistics.tsx
    • Statistics.css
    • ...

Ãœbungen

Aufgabe: Erstelle einfache wiederverwendbare Komponenten, die hauptsächlich für Styling verwendet werden

Beispiele:

Diese Komponenten sollten keine Interaktivität haben (keine Events)

Komponenten-Events

Komponenten-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

Komponenten-Events

Eventhandler werden als Funktionen definiert und via props übergeben / erhalten.

Eventnamen beginnen üblicherweise mit on, z.B. onChange, onClose, ...

Komponenten-Events

Beispiel:

<Rating
  value={prodRating}
  onChange={(newRating) => setProdRating(newRating)}
/>

Komponenten-Events

Beispiel für Prop-Types einer Rating-Komponente:

type Props = {
  value: number;
  onChange?: (value: number) => void;
};

Komponenten-Events

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>
  );
}

Komponenten-Events

Verwendung einer Rating-Komponente:

const [prodRating, setProdRating] = useState(3);
<Rating
  value={prodRating}
  onChange={(newRating) => setProdRating(newRating)}
/>

Ãœbungen

Ãœbungen

Aufgabe: Erstelle wiederverwendbare interaktive Komponenten (mit etwas Styling)

Beispiele:

Ãœbungen

Aufgabe: Teile die Todo-Anwendung in kleinere Komponenten, die mittels Props und Events kommunizieren (z.B. AddTodo, TodoItem, TodoList)

Ãœbungen

Aufgabe: Entwirf die Struktur von Props, Events und State für verschiedene Komponenten (z.B. Calendar, ColorPicker, BarChart, Tabs)