Ãœberblick

Geschichte

Klassenkomponenten waren vor der Einführung von Hooks (mit React 16.8, Februar 2019) weit verbreitet

Heute verlagert sich der Fokus hin zu Hooks

Klassenkomponenten vs Hooks

Gründe für die Verwendung von Hooks:

  • verringern oft Komplexität
  • einfachere Modularität
  • vermeiden Probleme mit this

Gründe für die Verwendung von Klassenkomponenten:

  • vermeiden von Problemen mit veraltetem State ("stale closures")
  • Instanzvariablen (in Klassenkomponenten) sind einfacher als Refs (in Funktionskomponenten)

Einfaches Beispiel

import { Component } from 'react';

class App extends Component {
  constructor(props) {
    // ...
    this.state = { name: 'World' };
  }

  render() {
    return <div>Hello, {this.state.name}!</div>;
  }
}

export default App;

Props

Props

Props können via this.props ausgelesen werden:

type TodoItemProps = {
  todo: Todo;
  onDelete: (id: number) => void;
};

class TodoItem extends Component<TodoItemProps> {
  render() {
    return (
      <li>
        {this.props.todo.completed ? 'DONE: ' : 'TODO: '}
        {this.props.todo.title}
      </li>
    );
  }
}

State

State in Klassenkomponenten

In Klassenkomponenten repräsentiert this.state den aktuellen state

this.state ist immer ein JavaScript-Objekt mit verschiedenen Einträgen (Properties)

Zustandsänderungen erfolgen über this.setState()

Struktur von this.state

this.state ist ein JavaScript-Objekt:

{
  "todos": [],
  "loadingStatus": "idle"
}

Typendeklaration

type TodoAppProps = {};
type TodoAppState = {
  todo: Array<Todo>;
  loadingStatus: string;
};

class TodoApp extends Component<
  TodoAppProps,
  TodoAppState
> {
  // ...
}

Initialisierung des States

Der State muss im Konstruktor initialisiert werden

Der Konstruktor erhält auch die Props der Komponente als Argument

Initialisierung des States

constructor(props: TodoAppProps) {
  super(props);
  this.state = {
    todos: [],
    loadingStatus: "idle",
  }
}

In JavaScript muss der Konstruktor der Elternklasse (Component) im Konstruktor aufgerufen werden (geschieht via super())

Änderung von State

this.setState({ loadingStatus: 'loading' });

setState überschreibt alle angegebenen Einträge im state-Objekt und lässt den Rest unverändert

Probleme mit "this"

Probleme mit "this"

in Klassenkomponenten - insbesondere in Eventhandlern - kann this manchmals falsch gesetzt sein

Probleme mit "this"

allgemeines Problem: Methodenaufrufe ohne Methodensyntax:

class Foo {
  constructor() {
    this.message = 'hello';
  }
  greet() {
    console.log(this.message);
  }
}
const foo = new Foo();
foo.greet(); // ok
const greet = foo.greet;
greet(); // not ok ("this" is undefined)

Probleme mit "this"

Problem in einem React-Rendering:

class Foo extends Component {
  // ...

  greet() {
    console.log(this.message);
  }
  render() {
    return <button onClick={this.greet}>hello</button>;
  }
}

Probleme mit "this"

Lösung A: Pfeil-Methoden:

class Foo extends Component {
  // ...
  greet = () => {
    console.log(this.message);
  };
  // ...
}

Lösung B: binden der Methode im Constructor:

  constructor() {
    // ...
    this.greet = this.greet.bind(this);
  }

Ãœbungen

Ãœbungen

Konvertiere bestehende Komponenten (z.B. AddTodo) von Funktionskomponenten zu Klassenkomponenten