Props und PropTypes in React

Avatar of Kingsley Silas
Kingsley Silas am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

React ermutigt Entwickler, indem es sie dazu anregt, eine Benutzeroberfläche (UI) in Komponenten aufzuteilen. Das bedeutet, dass es immer einen Bedarf geben wird, Daten von einer Komponente zur anderen zu übergeben – genauer gesagt, von einer Elternkomponente zur Kindkomponente –, da wir sie zusammenfügen und sie voneinander abhängig sind.

React nennt die zwischen Komponenten übergebenen Daten **Props**, und wir werden uns diese im Detail ansehen. Da wir über Props sprechen, wäre jeder Beitrag zu diesem Thema unvollständig, ohne **PropTypes** zu betrachten, da diese sicherstellen, dass Komponenten die richtigen Daten für die jeweilige Aufgabe übergeben.

Lassen Sie uns diese essentiellen, aber aufgeladenen Begriffe gemeinsam entpacken.

Props: Die weitergegebenen Daten

Grundsätzlich machen Props React zu dem Werkzeug, das es ist. React wurde entwickelt, um Dinge in Stücke zu zerlegen, die bei Bedarf bereitgestellt werden. Props sind definierende Merkmale, die von diesen Stücken gespeichert werden, und sie werden abgerufen und gesendet, wenn sie angefordert werden. Das Ergebnis ist ein Bildschirm, der nur das rendert, was er braucht, und nichts mehr, was die Ladezeiten von Seiten beschleunigt und die Gesamtleistung steigert.

Diese Daten können in verschiedenen Formen vorliegen: nämlich als Strings, Arrays und Funktionen. Die Möglichkeit, Daten zwischen Komponenten zu übergeben, also lassen Sie uns spezifisch aufschlüsseln, wie Daten abgerufen und übergeben werden.

Props übergeben und abrufen

Nehmen wir an, wir arbeiten an einer Anwendung, die eine Liste interessanter Demos von CodePen anzeigt.

Siehe den Pen Props Pen von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

Wir können die App als Sammlung von Komponenten veranschaulichen.

Die Liste der Pens wird Daten benötigen, insbesondere den Titel, die URL und den Autor für jede Demo, die die App anzeigt. Wir können diese Daten wie folgt erstellen.

const pensList = [
  {
    title: "Elastic Input[Google Chrome]",
    url: "https://codepen.io/andreasstorm/pen/JBGWBa",
    author: "Andreas Storm"
  },
  {
    title: "Phenomenon instances!",
    url: "https://codepen.io/cvaneenige/pen/ajNjaN",
    author: "Colin van Eenige"
  },
  {
    title: "cpc-forms experiment with css variables",
    url: "https://codepen.io/terabaud/pen/YjwYKv",
    author: "Lea Rosema"
  },
  {
    title: "Nuotron Logo Animation with Hover Effect",
    url: "https://codepen.io/YahiaRefaiea/pen/YjyZLm",
    author: "Yahia Refaiea"
  }
];

Die **App**-Komponente wird die Daten abrufen. Hier ist die grundlegende Struktur für diese Komponente.

const App = () => {
  return (
    <div>
      <PenList pens={pensList} />
    </div>
  );
}

Wir übergeben ein Array von Pens als Prop an die **PenList** (die wir gleich erstellen werden). Die Elternkomponente (PenList) greift auf die Daten (penList) zu, die **als pens Props an die Kindkomponente (Pen) übergeben werden**.

const PenList = props => {
  return (
    <React.Fragment>
      <h2>Interesting Pens on CodePen</h2>
      <ul>
        {props.pens.map(pen => {
          return (
            <li key={pen.url}>
              <Pen {...pen} />
            </li>
          );
        })}
      </ul>
    </React.Fragment>
  );
};

Die PenList-Komponente durchläuft die pens-Props (props.pens), um jedes Element als Pen-Komponente zurückzugeben. Wenn dies eine Klassenkomponente wäre, würden wir die pens-Props mit this präfixieren, so:

class PenList extends React.Component {
  render() {
    return (
      <React.Fragment>
        <h2>Interesting Pens on CodePen</h2>
        <ul>
          {
            this.props.pens.map(pen => {
              return (
                <li key={pen.url}>
                  <Pen {...pen} />
                </li>
              )
            })
          }
        </ul>
      </React.Fragment>
    )
  }
}

Das Nächste, was zu beachten ist, ist die Verwendung von key im Beispiel. Ein Schlüssel ist ein eindeutiger Identifikator, den wir jedem Element in unserer Liste zuweisen können, um sicherzustellen, dass wir die Elemente unterscheiden können. In diesem Fall ordnen wir den Schlüssel der URL jedes Pens zu. Es besteht keine Chance, dass zwei Elemente gleich sind, daher sind dies gute Daten für diesen Zweck.

Die verbleibenden Eigenschaften werden als Props an die Pen-Komponente übergeben. Hier ist die Pen-Komponente, die diese Props verwendet.

const Pen = props => {
  return (
    <div>
      <p>
        [{props.title}]
      </p>
      <p>Made by: {props.author}</p>
    </div>
  );
};

Beachten Sie, dass wir die Pen-Komponente (const Pen) konstruieren und sie nicht als Klasse (class PenList) definieren, wie wir es für die PenList-Komponente getan haben. Als solche können wir über props auf die Werte zugreifen. Das ist eine praktische kleine Abkürzung, die wir anstelle des erneuten Zuordnens von Pen zu den Daten verwenden können. Die Elternkomponente hat sie bereits, also reichen wir sie einfach weiter!

Funktionen über Props übergeben

Wir haben gerade das Übergeben eines Arrays von Daten als Props von einer Komponente zur anderen betrachtet, aber was ist, wenn wir stattdessen mit Funktionen arbeiten? React erlaubt es uns, Funktionen zwischen Komponenten zu übergeben, aber es ist ziemlich technisch. Dennoch ist es etwas, das Sie für bestimmte Anwendungsfälle tun möchten und das es wert ist, untersucht zu werden.

Nehmen wir ein einfaches Beispiel, sagen wir eine App, mit der Sie eine Aufgabenliste erstellen können. Sie wissen schon, eine To-Do-Liste, für Erledigungen, Projekte oder was auch immer. In dieser App befindet sich die Liste der Aufgaben in der **App**-Komponente, die die Elternkomponente ist. Die **Todo**-Komponente wird in diesem Szenario das Kind sein, und ihre einzige Aufgabe wird es sein, jede erstellte Aufgabe aufzulisten.

Im echten To-do-Listen-Format möchten wir nicht nur Aufgaben erstellen, sondern sie auch entfernen können, sobald eine Aufgabe erstellt wurde. Da sich die To-do-Liste in der App-Komponente befindet, müssen wir in der Lage sein, das spezifische Element zu identifizieren, das der Benutzer entfernen möchte, indem wir die id erhalten und dann das Element in der App-Komponente entfernen.

Klingt komplex? Hier ist, was wir vorhaben.

Siehe den Pen Props Pen 2 von Kingsley Silas Chijioke (@kinsomicrote) auf CodePen.

In Code zerlegt.

let todoCounter = 1;

class App extends React.Component {
  state = {
    list: [],
    item: ""
  };

  handleInputChange = event => {
    this.setState({ item: event.target.value });
  };

  handleSubmit = event => {
    event.preventDefault();
    const item = {
      id: todoCounter++,
      value: this.state.item.slice()
    };
    this.setState({
      list: this.state.list.concat(item),
      item: ""
    });
  };

  handleRemove = id => {
    this.setState({
      list: this.state.list.filter(c => c.id !== id)
    });
  };

  render() {
    return (
      <React.Fragment>
        <h2>Add Todo</h2>
        <div>
          <input
            type="text"
            value={this.state.item}
            onChange={this.handleInputChange}
          />
        </div>
        <div>
          <button type="submit" onClick={this.handleSubmit}>
            Add
          </button>
        </div>
        <div>
          <h3>Lists</h3>
          <ul>
            {this.state.list.map(item => {
              return (
                <li key={item.id}>
                  <Todo {...item} removeTodo={this.handleRemove} />
                </li>
              );
            })}
          </ul>
        </div>
      </React.Fragment>
    );
  }
}

Beachten Sie, dass wir todoCounter oben definiert und auf 1 gesetzt haben. Wir haben dies erstellt, damit wir eindeutige Schlüssel für die To-do-Elemente haben, genau wie wir es getan haben, als wir URLs für die Liste der Pens in unserem vorherigen Beispiel verwendet haben.

Die Methode zum Löschen von Aufgaben wird in der App-Komponente erstellt. In der render()-Funktion übergeben wir die To-do-Eigenschaften als Props an die Todo-Komponente. Wir übergeben auch die handleRemove()-Funktion als Prop namens removeTodo(). Wir werden dies in der Todo-Komponente verwenden, die so aussieht.

class Todo extends React.Component {
  deleteTodo = id => {
    this.props.removeTodo(id);
  };
  render() {
    return (
      <div>
        {this.props.value}
        <button onClick={() => this.deleteTodo(this.props.id)}>X</button>
      </div>
    );
  }
}

Wir müssen die id des To-do-Elements an removeTodo() in der Todo-Komponente übergeben, da wir den Zustand der App-Komponente ohne sie nicht aktualisieren können. Dies ist im Wesentlichen, wie wir eine Funktion über Props zwischen Komponenten übergeben können – ziemlich ähnlich wie wir es mit einem Array getan haben, der Unterschied ist, dass wir Funktionalität statt Rohdaten weitergeben.

PropTypes

PropTypes stellt sicher, dass der richtige Typ von Props an eine Komponente übergeben wird – und umgekehrt, dass die empfangende Komponente den richtigen Typ von Props erhält.

Wir können sie wie einen Football-Quarterback betrachten, der den Ball zu einem Receiver wirft. Der Quarterback möchte nur, dass seine Spieler den Ball empfangen. Und in diesem Sinne möchte der Quarterback, dass der Receiver einen Ball fängt – keine Katze, keine saure Gurke oder kein Taxi. PropTypes würde sicherstellen, dass das richtige Objekt (ein Ball) übergeben wird und dass es an den richtigen Empfänger (einen Spieler im Team) übergeben wird.

(Wenn doch nur Football PropTypes im echten Leben hätte!)

Um PropTypes nutzen zu können, müssen Sie das Paket als Abhängigkeit zu Ihrer Anwendung hinzufügen, indem Sie yarn add prop-types in der Kommandozeile ausführen.

Wir können PropTypes in unserer App verwenden, die interessante Pens anzeigt. Hier ist, wie wir es für die Pen-Komponente verwenden werden.

Pen.propTypes = {
  title: PropTypes.string,
  url: PropTypes.string,
  author: PropTypes.string
};

Wir deklarieren, dass die Props für title, url und author Strings sein sollten. Keine Zahlen. Keine Funktionen. Nur Strings.

Wenn wir die Props für author versehentlich in eine Zahl anstelle eines Strings ändern würden, so:

author: PropTypes.number

…würden wir einen Fehler erhalten.

Warning: Failed prop type: Invalid prop `author` of type `string` supplied to `Pen`, expected `number`.

PropTypes sind also nützlich, um Fehler zu erkennen. Wir können auch die Übergabe von Props erzwingen, indem wir isRequired verwenden.

Pen.propTypes = {
  title: PropTypes.string.isRequired,
  url: PropTypes.string.isRequired,
  author: PropTypes.string.isRequired
};

Die grundlegenden Datentypen, die Sie benötigen, sind String, Number, Boolean, Function usw.

Person.propTypes = {
  email: PropTypes.string,
  age: PropTypes.number,
  availability: PropTypes.bool,
  handleSubmit: PropTypes.func
}

Es gibt weitere verfügbare Typen und jede Menge Dokumentation dazu.

In Fällen, in denen ein Prop optional ist (d. h. nicht isRequired verwendet wird), können Sie einen Standardwert festlegen, um sicherzustellen, dass etwas übergeben wird.

Developer.defaultProps = {
  language: 'JavaScript' 
}

Damit hat der Sprach-Prop immer einen Wert, wenn er verwendet wird – auch wenn keiner bereitgestellt wird.

Zusammenfassung

Nun, das war ein breiter Überblick über props in React. Es ist so gut wie garantiert, dass Sie sowohl props als auch propTypes in einer React-Anwendung verwenden werden. Hoffentlich zeigt dieser Beitrag, wie wichtig sie für React als Ganzes sind, denn ohne sie hätten wir nichts, was zwischen Komponenten übergeben werden kann, wenn Interaktionen stattfinden. Sie sind ein Kernbestandteil der komponentengetriebenen und zustandsverwalteten Architektur, um die React aufgebaut ist.

Und propTypes sind ein zusätzlicher Bonus – wie eine integrierte Qualitätssicherungsprüfung, um Fehler zu erkennen und uns darüber zu informieren. Es ist schön zu wissen, dass sie uns bei der Arbeit unterstützen.