Erste Schritte mit der React Hooks API
Veröffentlicht: 2022-03-10Als React 16.8 Anfang Februar 2019 offiziell veröffentlicht wurde, wurde es mit einer zusätzlichen API ausgeliefert, mit der Sie den Status und andere Funktionen in React verwenden können, ohne eine Klasse zu schreiben. Diese zusätzliche API heißt Hooks und wird im React-Ökosystem immer beliebter, von Open-Source-Projekten bis hin zur Verwendung in Produktionsanwendungen.
React Hooks sind vollständig Opt-in, was bedeutet, dass das Umschreiben von vorhandenem Code nicht erforderlich ist, sie enthalten keine Breaking Changes und sie können mit der Veröffentlichung von React 16.8 verwendet werden. Einige neugierige Entwickler haben die Hooks-API bereits vor ihrer offiziellen Veröffentlichung genutzt, aber damals war sie nicht stabil und nur eine experimentelle Funktion. Jetzt ist es stabil und wird React-Entwicklern zur Verwendung empfohlen.
Hinweis : Wir werden nicht über React oder JavaScript im Allgemeinen sprechen. Gute Kenntnisse in ReactJS und JavaScript werden sich beim Durcharbeiten dieses Tutorials als nützlich erweisen.
Was sind Reaktionshaken?
React Hooks sind eingebaute Funktionen, die es React-Entwicklern ermöglichen, Zustands- und Lebenszyklusmethoden innerhalb funktionaler Komponenten zu verwenden, sie arbeiten auch mit vorhandenem Code zusammen, sodass sie leicht in eine Codebasis übernommen werden können. Die Art und Weise, wie Hooks der Öffentlichkeit präsentiert wurden, war, dass sie es Entwicklern ermöglichen, Zustände in funktionalen Komponenten zu verwenden, aber unter der Haube sind Hooks viel mächtiger als das. Sie ermöglichen React-Entwicklern die folgenden Vorteile:
- Verbesserte Wiederverwendung von Code;
- Bessere Code-Zusammensetzung;
- Bessere Standardeinstellungen;
- Teilen von nicht-visueller Logik mit der Verwendung von benutzerdefinierten Hooks;
- Flexibilität beim Auf- und Abbewegen des
components
.
Mit React Hooks erhalten Entwickler die Möglichkeit, funktionale Komponenten für fast alles zu verwenden, was sie tun müssen, vom bloßen Rendern der Benutzeroberfläche bis hin zum Umgang mit Status und auch Logik – was ziemlich ordentlich ist.
Motivation hinter der Freigabe von Reaktionshaken
Laut der offiziellen Dokumentation von ReactJS sind die folgenden Beweggründe hinter der Veröffentlichung von React Hooks:
- Die Wiederverwendung von zustandsbehafteter Logik zwischen Komponenten ist schwierig.
Mit Hooks können Sie Logik zwischen Ihren Komponenten wiederverwenden, ohne deren Architektur oder Struktur zu ändern. - Komplexe Komponenten können schwer zu verstehen sein.
Wenn Bauteile größer werden und viele Operationen ausführen, wird es auf Dauer schwer nachvollziehbar. Hooks lösen dies, indem sie es Ihnen ermöglichen, eine bestimmte einzelne Komponente in verschiedene kleinere Funktionen zu unterteilen, je nachdem, welche Teile dieser getrennten Komponente zusammenhängen (z. B. das Einrichten eines Abonnements oder das Abrufen von Daten), anstatt eine Aufteilung basierend auf Lebenszyklusmethoden erzwingen zu müssen. - Klassen sind ziemlich verwirrend.
Klassen sind ein Hindernis, um Reagieren richtig zu lernen; Sie müssten verstehen, wiethis
in JavaScript funktioniert, das sich von anderen Sprachen unterscheidet. React Hooks löst dieses Problem, indem es Entwicklern ermöglicht, die besten React-Funktionen zu nutzen, ohne Klassen verwenden zu müssen.
Die Hakenregeln
Es gibt zwei Hauptregeln, die strikt eingehalten werden müssen, wie vom React-Kernteam angegeben, in dem sie in der Hooks-Proposal-Dokumentation beschrieben sind.
- Achten Sie darauf, Hooks nicht innerhalb von Schleifen, Bedingungen oder verschachtelten Funktionen zu verwenden;
- Verwenden Sie nur Hooks innerhalb von React Functions.
Einfache Reaktionshaken
Es gibt 10 eingebaute Hooks, die mit React 16.8 ausgeliefert wurden, aber die grundlegenden (häufig verwendeten) Hooks umfassen:
-
useState()
-
useEffect()
-
useContext()
-
useReducer()
Dies sind die 4 grundlegenden Hooks, die häufig von React-Entwicklern verwendet werden, die React Hooks in ihre Codebasen aufgenommen haben.
useState()
Der useState()
ermöglicht es React-Entwicklern, den Status innerhalb funktionaler Komponenten zu aktualisieren, zu handhaben und zu manipulieren, ohne ihn in eine Klassenkomponente konvertieren zu müssen. Lassen Sie uns das folgende Code-Snippet verwenden, das eine einfache Alterszählerkomponente ist, und wir werden es verwenden, um die Leistungsfähigkeit und Syntax des useState()
-Hooks zu erklären.
function App() { const [age, setAge] = useState(19); const handleClick = () => setAge(age + 1) return <div> I am {age} Years Old <div> <button onClick={handleClick}>Increase my age! </button> </div> </div> }
Wie Sie bemerkt haben, sieht unsere Komponente ziemlich einfach, prägnant aus und ist jetzt eine funktionale Komponente und hat auch nicht den Grad an Komplexität, den eine Klassenkomponente haben würde.
Der useState()
erhält einen Anfangszustand als Argument und gibt dann zurück, indem die beiden Variablen im Array mithilfe der Array-Destrukturierung in JavaScript benannt werden können. Die erste Variable ist der tatsächliche Zustand, während die zweite Variable eine Funktion ist, die zum Aktualisieren des Zustands durch Bereitstellen eines neuen Zustands gedacht ist.
So sollte unsere Komponente aussehen, wenn sie in unserer React-Anwendung gerendert wird. Durch Klicken auf die Schaltfläche „Mein Alter erhöhen“ ändert sich der Status des Alters und die Komponente würde genau wie eine Klassenkomponente mit Status funktionieren.
useEffect()
Der useEffect()
akzeptiert eine Funktion, die effektiven Code enthalten würde. In funktionalen Komponenten dürfen Effekte wie Mutationen, Abonnements, Timer, Protokollierung und andere Effekte nicht innerhalb einer funktionalen Komponente platziert werden, da dies zu vielen Inkonsistenzen beim Rendern der Benutzeroberfläche und auch zu verwirrenden Fehlern führen würde.
Bei Verwendung des useEffect()
-Hooks wird die ihm übergebene effektive Funktion ausgeführt, direkt nachdem das Rendering auf dem Bildschirm angezeigt wurde. Effekte werden im Wesentlichen in die zwingende Art und Weise der Erstellung von Benutzeroberflächen eingesehen, die sich stark von der funktionalen Art und Weise von React unterscheidet.
Standardmäßig werden Effekte hauptsächlich nach Abschluss des Renderings ausgeführt, aber Sie haben die Möglichkeit, sie auch auszulösen, wenn sich bestimmte Werte ändern.
Der useEffect()
Hook kommt hauptsächlich für Nebeneffekte ins Spiel, die normalerweise für Interaktionen mit der Browser/DOM-API oder externen API-ähnlichen Datenabrufen oder Abonnements verwendet werden. Wenn Sie bereits mit der Funktionsweise von React-Lebenszyklusmethoden vertraut sind, können Sie sich useEffect()
-Hook auch als das Einhängen , Aktualisieren und Aushängen von Komponenten vorstellen – alles in einer Funktion kombiniert. Es ermöglicht uns, die Lebenszyklusmethoden in funktionalen Komponenten zu replizieren.
Wir werden die folgenden Code-Snippets verwenden, um die einfachste Möglichkeit zu erklären, die wir durch die Verwendung des useEffect()
-Hooks erreichen können.
Schritt 1: Definieren Sie den Status Ihrer Anwendung
import React, {useState} from 'react'; function App() { //Define State const [name, setName] = useState({firstName: 'name', surname: 'surname'}); const [title, setTitle] = useState('BIO'); return( <div> <h1>Title: {title}</h1> <h3>Name: {name.firstName}</h3> <h3>Surname: {name.surname}</h3> </div> ); }; export default App
Genau wie wir im vorherigen Abschnitt darüber gesprochen haben, wie der useState()
Hook verwendet wird, um den Zustand innerhalb funktionaler Komponenten zu handhaben, haben wir ihn in unserem Code-Snippet verwendet, um den Zustand für unsere App festzulegen, die meinen vollständigen Namen darstellt.
Schritt 2: Rufen Sie den useEffect-Hook auf
import React, {useState, useEffect} from 'react'; function App() { //Define State const [name, setName] = useState({firstName: 'name', surname: 'surname'}); const [title, setTitle] = useState('BIO'); //Call the use effect hook useEffect(() => { setName({FirstName: 'Shedrack', surname: 'Akintayo'}) }, [])//pass in an empty array as a second argument return( <div> <h1>Title: {title}</h1> <h3>Name: {name.firstName}</h3> <h3>Surname: {name.surname}</h3> </div> ); }; export default App
Wir haben jetzt den useEffect
Hook importiert und auch die useEffect()
Funktion verwendet, um den Status unserer name- und surname-Eigenschaft festzulegen, was ziemlich ordentlich und prägnant ist.
Sie haben vielleicht den useEffect
Hook im zweiten Argument bemerkt, das ein leeres Array ist; Dies liegt daran, dass es einen Aufruf von setFullName
enthält, der keine Liste von Abhängigkeiten enthält. Das Übergeben des zweiten Arguments verhindert eine unendliche Kette von Aktualisierungen ( componentDidUpdate()
) und ermöglicht es unserem useEffect()
, als Lebenszyklusmethode von componentDidMount
zu fungieren und einmal zu rendern, ohne bei jeder Änderung im Baum neu zu rendern.
Unsere React-App sollte nun so aussehen:
Wir können auch die title
unserer Anwendung innerhalb der Funktion useEffect()
ändern, indem wir die Funktion setTitle()
wie folgt aufrufen:
import React, {useState, useEffect} from 'react'; function App() { //Define State const [name, setName] = useState({firstName: 'name', surname: 'surname'}); const [title, setTitle] = useState('BIO'); //Call the use effect hook useEffect(() => { setName({firstName: 'Shedrack', surname: 'Akintayo'}) setTitle({'My Full Name'}) //Set Title }, [])// pass in an empty array as a second argument return( <div> <h1>Title: {title}</h1> <h3>Name: {name.firstName}</h3> <h3>Surname: {name.surname}</h3> </div> ); }; export default App
Nachdem unsere Anwendung neu gerendert wurde, zeigt sie jetzt den neuen Titel.
useContext()
Der useContext()
akzeptiert ein Kontextobjekt, dh den Wert, der von React.createContext
zurückgegeben wird, und gibt dann den aktuellen Kontextwert für diesen Kontext zurück.
Dieser Hook ermöglicht funktionalen Komponenten einen einfachen Zugriff auf Ihren React-App-Kontext. Bevor der useContext
Hook eingeführt wurde, mussten Sie einen contextType
oder einen <Consumer>
einrichten, um auf Ihren globalen Zustand zuzugreifen, der von einem Anbieter in einer Klassenkomponente weitergegeben wurde.
Grundsätzlich funktioniert der useContext
Hook mit der React Context-API, die eine Möglichkeit darstellt, Daten umfassend in Ihrer App zu teilen, ohne dass Sie Ihre App-Requisiten manuell durch verschiedene Ebenen weitergeben müssen. Jetzt macht useContext()
die Verwendung von Context ein wenig einfacher.
Die folgenden Codeausschnitte zeigen, wie die Context-API funktioniert und wie der useContext
Hook sie verbessert.
Die normale Art, die Kontext-API zu verwenden
import React from "react"; import ReactDOM from "react-dom"; const NumberContext = React.createContext(); function App() { return ( <NumberContext.Provider value={45}> <div> <Display /> </div> </NumberContext.Provider> ); } function Display() { return ( <NumberContext.Consumer> {value => <div>The answer to the question is {value}.</div>} </NumberContext.Consumer> ); } ReactDOM.render(<App />, document.querySelector("#root"));
Lassen Sie uns nun das Code-Snippet aufschlüsseln und jedes Konzept erläutern.
Unten erstellen wir einen Kontext namens NumberContext
. Es soll ein Objekt mit zwei Werten zurückgeben: { Provider, Consumer }
.
const NumberContext = React.createContext();
Dann verwenden wir den Provider
Wert, der von dem von uns erstellten NumberContext
zurückgegeben wurde, um einen bestimmten Wert für alle untergeordneten Elemente verfügbar zu machen.
function App() { return ( <NumberContext.Provider value={45}> <div> <Display /> </div> </NumberContext.Provider> ); }
Damit können wir den Consumer
-Wert verwenden, der von dem von uns erstellten NumberContext
zurückgegeben wurde, um den Wert zu erhalten, den wir allen untergeordneten Elementen zur Verfügung gestellt haben. Wie Sie bemerkt haben, hat diese Komponente keine Requisiten erhalten.
function Display() { return ( <NumberContext.Consumer> {value => <div>The answer to the question is {value}.</div>} </NumberContext.Consumer> ); } ReactDOM.render(<App />, document.querySelector("#root"));
Beachten Sie, wie wir den Wert von der App
Komponente in die Display
Komponente übertragen konnten, indem wir unseren Inhalt in ein NumberContext.Consumer
verpackten und die render props-Methode verwendeten, um den Wert abzurufen und zu rendern.
Alles funktioniert gut und die von uns verwendete Render-Requisiten-Methode ist ein wirklich gutes Muster für den Umgang mit dynamischen Daten, aber auf lange Sicht führt es zu unnötigen Verschachtelungen und Verwirrung, wenn Sie nicht daran gewöhnt sind.
Verwenden der useContext-Methode
Um die useContext
Methode zu erklären, schreiben wir die Display
-Komponente mit dem useContext-Hook um.
// import useContext (or we could write React.useContext) import React, { useContext } from 'react'; // old code goes here function Display() { const value = useContext(NumberContext); return <div>The answer is {value}.</div>; }
Das ist alles, was wir tun müssen, um unseren Wert zu zeigen. Ziemlich ordentlich, oder? Sie rufen den useContext()
auf und übergeben das von uns erstellte Kontextobjekt, und wir holen uns den Wert daraus.
Hinweis: Vergessen Sie nicht, dass das Argument, das an den useContext-Hook übergeben wird, das Kontextobjekt selbst sein muss und dass jede Komponente, die useContext aufruft, immer neu gerendert wird, wenn sich der Kontextwert ändert.
useReducer()
Der Hook useReducer
wird zur Behandlung komplexer Zustände und Zustandsübergänge verwendet. Es nimmt eine reducer
und auch eine Anfangszustandseingabe auf; dann gibt es den aktuellen Zustand und auch eine dispatch
-Funktion als Ausgabe mittels Array-Destrukturierung zurück.
Der folgende Code ist die richtige Syntax für die Verwendung des useReducer
.
const [state, dispatch] = useReducer(reducer, initialArg, init);
Es ist eine Art Alternative zum useState
Hook; es ist normalerweise vorzuziehen, useState
zu verwenden, wenn Sie eine komplexe Zustandslogik haben, die mit mehreren Unterwerten zu tun hat, oder wenn der nächste Zustand vom vorherigen abhängig ist.
Andere Reaktionshaken erhältlich
useCallback | Dieser Hook gibt eine Callback-Funktion zurück, die gespeichert ist und sich nur ändert, wenn sich eine Abhängigkeit in der Abhängigkeitsstruktur ändert. |
useMemo | Dieser Hook gibt einen gespeicherten Wert zurück, Sie können eine „create“-Funktion und auch ein Array von Abhängigkeiten übergeben. Der zurückgegebene Wert verwendet den gespeicherten Wert nur dann erneut, wenn sich eine der Abhängigkeiten im Abhängigkeitsbaum ändert. |
useRef | Dieser Hook gibt ein änderbares Ref-Objekt zurück, dessen .current Eigenschaft mit dem übergebenen Argument ( initialValue ) initialisiert wird. Das zurückgegebene Objekt ist für die gesamte Lebensdauer der Komponente verfügbar. |
useImperativeHandle | Dieser Hook wird zum Anpassen des Instanzwerts verwendet, der für übergeordnete Komponenten verfügbar gemacht wird, wenn Refs in React verwendet werden. |
useLayoutEffect | Dieser Hook ähnelt dem useEffect Hook, feuert jedoch synchron nach allen DOM-Mutationen. Es wird auch auf die gleiche Weise wie componentDidUpdate und componentDidMount . |
useDebugValue | Dieser Hook kann verwendet werden, um ein Label für benutzerdefinierte Hooks in den React Dev Tools anzuzeigen. Es ist sehr nützlich für das Debugging mit den React Dev Tools. |
Benutzerdefinierte Reaktionshaken
Ein „benutzerdefinierter Hook“ ist eine JavaScript-Funktion, deren Namen das Wort use
vorangestellt ist und die verwendet werden kann, um andere Hooks aufzurufen. Außerdem können Sie Komponentenlogik in wiederverwendbare Funktionen extrahieren; Sie sind normale JavaScript-Funktionen, die andere darin enthaltene Hooks verwenden können, und enthalten auch eine gemeinsame zustandsbehaftete Logik, die in mehreren Komponenten verwendet werden kann.
Die folgenden Codeausschnitte zeigen ein Beispiel für einen benutzerdefinierten React Hook zur Implementierung von unendlichem Scrollen (von Paulo Levy):
import { useState } from "react"; export const useInfiniteScroll = (start = 30, pace = 10) => { const [limit, setLimit] = useState(start); window.onscroll = () => { if ( window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight ) { setLimit(limit + pace); } }; return limit; };
Dieser benutzerdefinierte Hook akzeptiert zwei Argumente, nämlich start
und pace
. Das Startargument ist die Anfangsanzahl von Elementen, die gerendert werden sollen, während das Tempoargument die nachfolgende Anzahl von Elementen ist, die gerendert werden sollen. Standardmäßig sind die start
und pace
Argumente auf 30
bzw. 10
gesetzt, was bedeutet, dass Sie den Hook tatsächlich ohne Argumente aufrufen können und stattdessen diese Standardwerte verwendet werden.
Um diesen Hook also in einer React-App zu verwenden, würden wir ihn mit einer Online-API verwenden, die „gefälschte“ Daten zurückgibt:
import React, { useState, useEffect } from "react"; import { useInfiniteScroll } from "./useInfiniteScroll"; const App = () => { let infiniteScroll = useInfiniteScroll(); const [tableContent, setTableContent] = useState([]); useEffect(() => { fetch("https://jsonplaceholder.typicode.com/todos/") .then(response => response.json()) .then(json => setTableContent(json)); }, []); return ( <div style={{ textAlign: "center" }}> <table> <thead> <tr> <th>User ID</th> <th>Title</th> </tr> </thead> <tbody> {tableContent.slice(0, infiniteScroll).map(content => { return ( <tr key={content.id}> <td style={{ paddingTop: "10px" }}>{content.userId}</td> <td style={{ paddingTop: "10px" }}>{content.title}</td> </tr> ); })} </tbody> </table> </div> ); }; export default App;
Der obige Code rendert eine Liste gefälschter Daten ( Benutzer- userID
und title
), die den unendlichen Scroll-Hook verwenden, um die ursprüngliche Anzahl von Daten auf dem Bildschirm anzuzeigen.
Fazit
Ich hoffe, es hat Ihnen Spaß gemacht, dieses Tutorial durchzuarbeiten. In den folgenden Referenzen können Sie jederzeit mehr über React Hooks lesen.
Wenn Sie Fragen haben, können Sie diese im Kommentarbereich hinterlassen, und ich beantworte gerne jede einzelne!
Das unterstützende Repository für diesen Artikel ist auf Github verfügbar.
Ressourcen und weiterführende Literatur
- „Hooks-API-Referenz“, React.js-Dokumentation
- „Was sind Reaktionshaken?“, Robin Wieruch
- „So funktioniert der
useContext
Hook“, Dave Ceddia - „Hooks reagieren: Verwendung
useEffect()
“, Hossein Ahmadi, Medium - „Schreiben Sie Ihre eigenen benutzerdefinierten Reaktionshaken“, Aayush Jaiswal, Medium
- „Leicht verständliche React-Hook-Rezepte“, Gabe Ragland, useHooks()