Schreiben einer API für React-Komponenten, Teil 1: Erstellen Sie keine widersprüchlichen Requisiten
Schreiben einer API für Reaktionskomponenten, Teil 2: Geben Sie dem Verhalten Namen, nicht der Interaktion
Schreiben einer API für React-Komponenten, Teil 3: Die Reihenfolge der Requisiten ist wichtig
Schreiben einer API für React Components, Teil 4: Vorsicht vor der Apropacalypse!
Schreiben einer API für Reaktionskomponenten, Teil 5: Verwenden Sie einfach die Komposition
Wir schreiben API für React-Komponenten, Teil 6: Wir erstellen die Kommunikation zwischen Komponenten
Wir haben eine Schalterkomponente - Switch
, der Requisiten akzeptiert, nennen wir es something
.
Ein Entwickler, der unsere Komponente verwendet, kann eine Funktion übergeben, die wir aufrufen, wenn sich der Wert ändert.

<Switch something={fn} />
Mit React können wir prop nach clickHandler
onClick
: handler
/ clickHandler
/ onClick
/ onToggle
usw.
Die Konvention, mit der der Name des Ereignishandlers beispielsweise bei onClick
, onClick
. Dies liegt daran, dass die HTML-Spezifikation viele Handler enthält, die dieser Konvention bereits folgen: onkeydown
, onchange
, onclick
usw.
Die Wiederverwendung einer bestehenden Vereinbarung ist eine großartige Idee, da sich Entwickler nicht an etwas Neues erinnern müssen.
OK, was ist mit onClick
?
<Switch onClick={fn} />
Hier bin ich kein Unterstützer des Namens onClick
. Ein solcher Name deutet darauf hin, dass ein Mausklick die einzige Möglichkeit ist, mit dieser Komponente zu interagieren.
Benutzer auf einem mobilen Gerät können den Schalter mit einem Finger drücken oder nach rechts ziehen. Sehbehinderte Benutzer können es mit Bildschirmlese-Software und Tastaturtasten verwenden.
Als Entwickler, der diese Komponente verwendet, möchte ich nicht darüber nachdenken, wie Endbenutzer mit dieser Komponente interagieren. Ich möchte nur eine Funktion anhängen, die aufgerufen wird, wenn sich der Wert ändert.
Geben Sie Namen für Ihre API an, die keine Möglichkeit zur Interaktion angeben:
<Switch onToggle={fn} />
Das macht doch Sinn, oder? Kippschalter ( toggles
) zwischen zwei Werten.
Innerhalb einer Komponente möchten Sie möglicherweise alle möglichen Interaktionen in derselben Funktion vertreten
function Switch(props) { return ( <div className="switch" /* */ onClick={props.onToggle} onKeyDown={function(event) { /* enter , event */ if (event.key === 'Enter') props.onToggle(event) }} onDrag={function(event) { /* */ if (event.toElement === rightSide) props.onToggle(event) }} /> ) }
Wir haben alle Optionen berücksichtigt, um unseren Benutzern (Entwicklern) eine klare API zu geben.
Lassen Sie uns nun über die Texteingabekomponente sprechen.

<TextInput />
HTML hat ein onchange-Attribut . Die React-Dokumentation verwendet in ihren Beispielen onChange
. Anscheinend besteht in dieser Hinsicht ein Konsens.
<TextInput onChange={fn} />
Sehr einfach.
Lassen Sie uns nun beide Komponenten nebeneinander stellen.

<TextInput onChange={fn} /> <Switch onToggle={fn} />
Sehen Sie etwas Seltsames?
Trotz der Tatsache, dass beide Komponenten das gleiche Verhalten erfordern, wird prop unterschiedlich aufgerufen. Diese Requisiten sind perfekt für ihre jeweiligen Komponenten, aber wenn Sie Ihre Komponenten zusammen betrachten, sieht es ziemlich kontrovers aus.
Ein Entwickler, der diese Komponenten verwendet, muss immer den Namen der Requisite überprüfen, bevor er sie verwendet.
Hier ist also Tipp 2: Streben Sie nach konsistenten Requisiten zwischen den Komponenten . Das gleiche Verhalten sollte für alle Komponenten die gleiche Stütze haben.
Dieser Rat kann auch wie folgt formuliert werden: Streben Sie einen minimalen API-Bereich an . Sie müssen die Anzahl der APIs begrenzen, die ein Entwickler beherrschen muss, bevor er produktiv arbeiten kann.
Ich möchte sagen, dass alle Verdienste zu diesem Thema Sebastian Markbåge zu verdanken sind . (Seine Präsentation: Minimale API-Oberfläche )
Um diesen Rat umzusetzen, müssen Sie eine Requisite auswählen und in allen Ihren Komponenten verwenden. Von den beiden Requisiten in unserem Beispiel befindet sich onChange
auch in der HTML-Spezifikation, sodass einige Entwickler dies möglicherweise erkennen.

<TextInput onChange={fn} /> <Switch onChange={fn} /> <Select onChange={fn} /> // etc.
Die Konsistenz zwischen den Komponenten und damit die Einfachheit des Lernens Ihrer API überwiegen die Auswahl der „idealen“ Requisite für eine einzelne Komponente.
Ein kleiner Bonus.
Lassen Sie uns über die Signatur dieser Funktion sprechen.
<TextInput onChange={fn} />
Der onChange
Ereignishandler (in diesem Beispiel fn
) empfängt ein Argument - event
.
Es funktioniert bei jeder Änderung. Sie können eine Reihe nützlicher Informationen von dieser Veranstaltung erhalten.
function fn(event) { console.log(event.target)
Höchstwahrscheinlich sind die meisten Entwickler an event.target.value
interessiert, damit sie es für einige andere Aufgaben verwenden können - Verwendung im Status, Formular senden usw.
Bei unserer Switch
Komponente repräsentiert jede Aktion ein separates "Ereignis" - event
. Dieses event
über verschiedene Eigenschaften zum Klicken und Ziehen. Wie stellen wir sicher, dass die API konsistent ist?
Wir können event.target.value
für jedes "Ereignis" manuell event.target.value
:
function Switch(props) { const fireHandler = event => { const newValue = !oldValue event.target.value = newValue props.onChange(event) } return ( <div className="switch" /* */ onClick={fireHandler} onKeyDown={function(event) { if (event.key === 'Enter') fireHandler(event) }} onDrag={function(event) { if (event.toElement === rightSide) fireHandler(event) }} /> ) }