Nützliche Reaktionshaken, die Sie in Ihren Projekten verwenden können

Veröffentlicht: 2022-03-10
Kurze Zusammenfassung ↬ Klassenbasierte React-Komponenten sind chaotisch, verwirrend und schwierig für Menschen und Maschinen. Aber vor React 16.8 waren klassenbasierte Komponenten für alle Projekte obligatorisch, die Zustände, Lebenszyklusmethoden und viele andere wichtige Funktionalitäten erfordern. All dies änderte sich mit der Einführung von Hooks in React 16.8. Haken sind Game-Changer. Sie haben React vereinfacht, es übersichtlicher, einfacher zu schreiben und zu debuggen und auch die Lernkurve verkürzt.

Hooks sind einfach Funktionen, mit denen Sie sich in React-Funktionen einklinken oder diese nutzen können . Sie wurden auf der React Conf 2018 vorgestellt, um drei Hauptprobleme von Klassenkomponenten anzugehen: Wrapper-Hölle, riesige Komponenten und verwirrende Klassen. Hooks verleihen React-Funktionskomponenten Leistung und ermöglichen es, eine ganze Anwendung damit zu entwickeln.

Die oben erwähnten Probleme der Klassenkomponenten sind miteinander verbunden und das Lösen des einen ohne das andere könnte weitere Probleme einführen. Zum Glück haben Hooks alle Probleme einfach und effizient gelöst und gleichzeitig Platz für interessantere Funktionen in React geschaffen. Hooks ersetzen keine bereits bestehenden React-Konzepte und -Klassen, sie stellen lediglich eine API bereit, um direkt darauf zuzugreifen.

Das React-Team hat in React 16.8 mehrere Hooks eingeführt. Sie können jedoch auch Hooks von Drittanbietern in Ihrer Anwendung verwenden oder sogar einen benutzerdefinierten Hook erstellen. In diesem Tutorial werfen wir einen Blick auf einige nützliche Hooks in React und wie man sie verwendet. Wir werden mehrere Codebeispiele für jeden Hook durchgehen und auch untersuchen, wie Sie einen benutzerdefinierten Hook erstellen würden.

Hinweis: Dieses Tutorial erfordert ein grundlegendes Verständnis von Javascript (ES6+) und React.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Motivation hinter Haken

Wie bereits erwähnt, wurden Hooks erstellt, um drei Probleme zu lösen: Wrapper-Hölle, riesige Komponenten und verwirrende Klassen. Werfen wir einen genaueren Blick auf diese.

Wrapper-Hölle

Komplexe Anwendungen, die mit Klassenkomponenten erstellt wurden, geraten leicht in die Wrapper-Hölle. Wenn Sie die Anwendung in den React Dev Tools untersuchen, werden Sie tief verschachtelte Komponenten bemerken. Dies macht es sehr schwierig, mit den Komponenten zu arbeiten oder sie zu debuggen. Diese Probleme könnten zwar mit höherwertigen Komponenten und Render-Requisiten gelöst werden, erfordern jedoch eine geringfügige Änderung Ihres Codes. Dies könnte in einer komplexen Anwendung zu Verwirrung führen.

Hooks sind einfach zu teilen, Sie müssen Ihre Komponenten nicht ändern, bevor Sie die Logik wiederverwenden.

Ein gutes Beispiel hierfür ist die Verwendung der Redux connect Higher Order Component (HOC) zum Abonnieren des Redux Stores. Wie bei allen HOCs müssen Sie zur Verwendung der Connect-HOC die Komponente zusammen mit den definierten Funktionen höherer Ordnung exportieren. Im Fall von connect haben wir etwas von dieser Form.

 export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)

Wobei mapStateToProps und mapDispatchToProps zu definierende Funktionen sind.

Während man in der Hooks-Ära mit den Hooks useSelector und useDispatch von Redux problemlos das gleiche Ergebnis sauber und prägnant erzielen kann.

Riesige Komponenten

Klassenkomponenten enthalten normalerweise Nebeneffekte und zustandsbehaftete Logik. Mit zunehmender Komplexität der Anwendung wird die Komponente häufig chaotisch und verwirrend. Dies liegt daran, dass erwartet wird, dass die Nebenwirkungen eher durch Lebenszyklusmethoden als durch Funktionalität organisiert werden. Es ist zwar möglich, die Komponenten aufzuteilen und einfacher zu gestalten, dies führt jedoch häufig zu einer höheren Abstraktionsebene.

Hooks organisieren Seiteneffekte nach Funktionalität und es ist möglich, eine Komponente basierend auf der Funktionalität in Teile aufzuteilen.

Verwirrende Klassen

Klassen sind im Allgemeinen ein schwierigeres Konzept als Funktionen. Klassenbasierte React-Komponenten sind ausführlich und für Anfänger etwas schwierig. Wenn Sie mit Javascript noch nicht vertraut sind, könnten Sie feststellen, dass Funktionen aufgrund ihrer schlanken Syntax im Vergleich zu Klassen einfacher zu erlernen sind. Die Syntax könnte verwirrend sein; Manchmal ist es möglich, das Binden eines Ereignishandlers zu vergessen, was den Code beschädigen könnte.

React löst dieses Problem mit funktionalen Komponenten und Hooks, sodass sich Entwickler auf das Projekt und nicht auf die Codesyntax konzentrieren können.

Beispielsweise liefern die folgenden beiden React-Komponenten genau das gleiche Ergebnis.

 import React, { Component } from "react"; export default class App extends Component { constructor(props) { super(props); this.state = { num: 0 }; this.incrementNumber = this.incrementNumber.bind(this); } incrementNumber() { this.setState({ num: this.state.num + 1 }); } render() { return ( <div> <h1>{this.state.num}</h1> <button onClick={this.incrementNumber}>Increment</button> </div> ); } }
 import React, { useState } from "react"; export default function App() { const [num, setNum] = useState(0); function incrementNumber() { setNum(num + 1); } return ( <div> <h1>{num}</h1> <button onClick={incrementNumber}>Increment</button> </div> ); }

Das erste Beispiel ist eine klassenbasierte Komponente, während das zweite eine funktionale Komponente ist. Obwohl dies ein einfaches Beispiel ist, beachten Sie, wie falsch das erste Beispiel im Vergleich zum zweiten ist.

Die Hooks-Konvention und -Regeln

Bevor Sie sich mit den verschiedenen Hooks befassen, könnte es hilfreich sein, einen Blick auf die Konventionen und Regeln zu werfen, die für sie gelten. Hier sind einige der Regeln, die für Haken gelten.

  1. Die Namenskonvention von Hooks sollte mit dem Präfix use beginnen. Wir können also useState , useEffect usw. haben. Wenn Sie moderne Code-Editoren wie Atom und VSCode verwenden, könnte das ESLint-Plugin eine sehr nützliche Funktion für React-Hooks sein. Das Plugin bietet nützliche Warnungen und Hinweise zu Best Practices.
  2. Hooks müssen auf der obersten Ebene einer Komponente vor der return-Anweisung aufgerufen werden. Sie können nicht innerhalb einer bedingten Anweisung, Schleife oder verschachtelten Funktion aufgerufen werden.
  3. Hooks müssen von einer React-Funktion aufgerufen werden (innerhalb einer React-Komponente oder eines anderen Hooks). Es sollte nicht von einer Vanilla JS-Funktion aufgerufen werden.

Der useState Hook

Der useState Hook ist der einfachste und nützlichste React-Hook. Wie andere integrierte Hooks muss dieser Hook aus react importiert werden, um in unserer Anwendung verwendet zu werden.

 import {useState} from 'react'

Um den Zustand zu initialisieren, müssen wir sowohl den Zustand als auch seine Aktualisierungsfunktion deklarieren und einen Anfangswert übergeben.

 const [state, updaterFn] = useState('')

Wir können unseren Status und unsere Updater-Funktion beliebig nennen, aber per Konvention ist das erste Element des Arrays unser Status, während das zweite Element die Updater-Funktion ist. Es ist üblich, unserer Updater-Funktion das Präfixset voranzustellen, gefolgt vom Namen unseres Bundesstaates in Camel-Case-Form.

Lassen Sie uns beispielsweise einen Zustand festlegen, um Zählwerte zu speichern.

 const [count, setCount] = useState(0)

Beachten Sie, dass der Anfangswert unseres count auf 0 und nicht auf eine leere Zeichenfolge gesetzt ist. Mit anderen Worten, wir können unseren Zustand mit jeder Art von JavaScript-Variablen initialisieren, nämlich Zahl, Zeichenfolge, boolescher Wert, Array, Objekt und sogar BigInt. Es gibt einen klaren Unterschied zwischen dem Festlegen von Zuständen mit dem useState -Hook und klassenbasierten Komponentenzuständen. Es ist bemerkenswert, dass der useState Hook ein Array zurückgibt, das auch als Statusvariablen bekannt ist, und im obigen Beispiel haben wir das Array in state und die updater Funktion destrukturiert.

Rendern von Komponenten

Das Festlegen von Zuständen mit dem useState Hook bewirkt, dass die entsprechende Komponente neu gerendert wird. Dies geschieht jedoch nur, wenn React einen Unterschied zwischen dem vorherigen oder alten Zustand und dem neuen Zustand feststellt. React führt den Zustandsvergleich mit dem Object.is Algorithmus durch.

Zustände setzen mit useState

Unser count kann auf neue Statuswerte gesetzt werden, indem der neue Wert einfach wie folgt an die setCount Updater-Funktion übergeben wird: setCount(newValue) .

Diese Methode funktioniert, wenn wir nicht auf den vorherigen Statuswert verweisen möchten. Wenn wir das tun möchten, müssen wir eine Funktion an die Funktion setCount .

Angenommen, wir möchten unsere count jedes Mal um 5 erhöhen, wenn auf eine Schaltfläche geklickt wird, könnten wir Folgendes tun.

 import {useState} from 'react' const CountExample = () => { // initialize our count state const [count, setCount] = useState(0) // add 5 to to the count previous state const handleClick = () =>{ setCount(prevCount => prevCount + 5) } return( <div> <h1>{count} </h1> <button onClick={handleClick}>Add Five</button> </div> ) } export default CountExample

Im obigen Code haben wir zuerst den useState Hook aus „ react “ importiert und dann den count mit einem Standardwert von 0 initialisiert. Wir haben einen onClick -Handler erstellt, um den Wert von „ count “ um 5 zu erhöhen, wenn auf die Schaltfläche geklickt wird. Dann haben wir das Ergebnis in einem h1 -Tag angezeigt.

Festlegen von Arrays und Objektzuständen

Zustände für Arrays und Objekte können ähnlich wie andere Datentypen gesetzt werden. Wenn wir jedoch bereits vorhandene Werte beibehalten möchten, müssen wir beim Setzen von Zuständen den Spread-Operator ES6 verwenden.

Der Spread-Operator in Javascript wird verwendet, um ein neues Objekt aus einem bereits vorhandenen Objekt zu erstellen. Dies ist hier nützlich, da React die Zustände mit der Object.is Operation vergleicht und dann entsprechend neu rendert.

Betrachten wir den folgenden Code zum Festlegen von Zuständen beim Klicken auf eine Schaltfläche.

 import {useState} from 'react' const StateExample = () => { //initialize our array and object states const [arr, setArr] = useState([2, 4]) const [obj, setObj] = useState({num: 1, name: 'Desmond'}) // set arr to the new array values const handleArrClick = () =>{ const newArr = [1, 5, 7] setArr([...arr, ...newArr]) } // set obj to the new object values const handleObjClick = () =>{ const newObj = {name: 'Ifeanyi', age: 25} setObj({...obj, ...newObj}) } return( <div> <button onClick ={handleArrClick}>Set Array State</button> <button onClick ={handleObjClick}>Set Object State</button> </div> ) } export default StateExample

Im obigen Code haben wir zwei Zustände arr und obj und sie mit einigen Array- bzw. Objektwerten initialisiert. Anschließend haben wir onClick Handler mit den Namen handleArrClick und handleObjClick , um die Zustände des Arrays bzw. des Objekts festzulegen. Wenn handleArrClick wird, rufen wir setArr und verwenden den Spread-Operator von ES6, um bereits vorhandene Array-Werte zu verteilen und newArr hinzuzufügen.

Dasselbe haben wir für den handleObjClick Handler gemacht. Hier haben wir setObj aufgerufen, die vorhandenen Objektwerte mit dem Spread-Operator von ES6 verteilt und die Werte von name und age aktualisiert.

Asynchrone useState

Wie wir bereits gesehen haben, setzen wir Zustände mit useState , indem wir einen neuen Wert an die Updater-Funktion übergeben. Wenn der Updater mehrmals aufgerufen wird, werden die neuen Werte einer Warteschlange hinzugefügt, und das erneute Rendern erfolgt entsprechend mithilfe des JavaScript- Object.is Vergleichs.

Die Zustände werden asynchron aktualisiert. Das bedeutet, dass der neue Zustand zuerst zu einem schwebenden Zustand hinzugefügt wird und danach der Zustand aktualisiert wird. Sie erhalten also möglicherweise immer noch den alten Statuswert, wenn Sie sofort auf den Status zugreifen, wenn er festgelegt ist.

Betrachten wir das folgende Beispiel, um dieses Verhalten zu beobachten.

Im obigen Code haben wir mithilfe des useState -Hooks einen count erstellt. Wir haben dann einen onClick -Handler erstellt, um den count zu erhöhen, wenn auf die Schaltfläche geklickt wird. Beachten Sie, dass, obwohl der count zugenommen hat, wie im h2 -Tag angezeigt, der vorherige Status immer noch in der Konsole protokolliert wird. Dies liegt an der asynchronen Natur des Hooks.

Wenn wir den neuen Zustand erhalten möchten, können wir ihn auf ähnliche Weise handhaben wie mit asynchronen Funktionen. Hier ist eine Möglichkeit, das zu tun.

Hier haben wir den erstellten newCountValue gespeichert, um den aktualisierten Zählwert zu speichern und dann den count mit dem aktualisierten Wert festzulegen. Dann haben wir den aktualisierten Zählwert in der Konsole protokolliert.

Der useEffect Hook

useEffect ist ein weiterer wichtiger React-Hook, der in den meisten Projekten verwendet wird. Sie verhält sich ähnlich wie die Lebenszyklusmethoden componentDidMount , componentWillUnmount und componentDidUpdate der klassenbasierten Komponente. useEffect bietet uns die Möglichkeit, zwingende Codes zu schreiben, die Nebenwirkungen auf die Anwendung haben können. Beispiele für solche Auswirkungen sind Protokollierung, Abonnements, Mutationen usw.

Der Benutzer kann entscheiden, wann useEffect ausgeführt wird, wenn es jedoch nicht gesetzt ist, werden die Nebeneffekte bei jedem Rendern oder erneuten Rendern ausgeführt.

Betrachten Sie das folgende Beispiel.

 import {useState, useEffect} from 'react' const App = () =>{ const [count, setCount] = useState(0) useEffect(() =>{ console.log(count) }) return( <div> ... </div> ) }

Im obigen Code haben wir einfach count in useEffect protokolliert. Dies wird nach jedem Rendern der Komponente ausgeführt.

Manchmal möchten wir den Hook vielleicht einmal (auf der Halterung) in unserer Komponente ausführen. Wir können dies erreichen, indem wir einen zweiten Parameter für useEffect Hook bereitstellen.

 import {useState, useEffect} from 'react' const App = () =>{ const [count, setCount] = useState(0) useEffect(() =>{ setCount(count + 1) }, []) return( <div> <h1>{count}</h1> ... </div> ) }

Der Hook useEffect hat zwei Parameter, der erste Parameter ist die Funktion, die wir ausführen möchten, während der zweite Parameter ein Array von Abhängigkeiten ist. Wenn der zweite Parameter nicht angegeben wird, wird der Hook kontinuierlich ausgeführt.

Indem wir eine leere eckige Klammer an den zweiten Parameter des Hooks übergeben, weisen wir React an, den useEffect Hook nur einmal auf dem Mount auszuführen. Dadurch wird der Wert 1 im h1 -Tag angezeigt, da die Zählung einmal von 0 auf 1 aktualisiert wird, wenn die Komponente bereitgestellt wird.

Wir könnten unseren Nebeneffekt auch ausführen lassen, wenn sich einige abhängige Werte ändern. Dies kann durch Übergeben dieser Werte in der Liste der Abhängigkeiten erfolgen.

Zum Beispiel könnten wir den useEffect so machen, dass er immer dann ausgeführt wird, wenn sich die count wie folgt ändert.

 import { useState, useEffect } from "react"; const App = () => { const [count, setCount] = useState(0); useEffect(() => { console.log(count); }, [count]); return ( <div> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default App;

Der useEffect wird ausgeführt, wenn eine dieser beiden Bedingungen erfüllt ist.

  1. On mount – nachdem die Komponente gerendert wurde.
  2. Wenn sich der Wert von count ändert.

Beim Mounten wird der Ausdruck console.log ausgeführt und die count auf 0 protokolliert. Sobald die count aktualisiert ist, ist die zweite Bedingung erfüllt, sodass useEffect erneut ausgeführt wird, dies wird fortgesetzt, wenn auf die Schaltfläche geklickt wird.

Sobald wir useEffect das zweite Argument übergeben, wird erwartet, dass wir alle Abhängigkeiten daran übergeben. Wenn Sie ESLINT installiert haben, wird ein Lint-Fehler angezeigt, wenn eine Abhängigkeit nicht an die Parameterliste übergeben wird. Dies könnte auch dazu führen, dass sich der Nebeneffekt unerwartet verhält, insbesondere wenn er von den nicht übergebenen Parametern abhängt.

Den Effekt bereinigen

useEffect ermöglicht es uns auch, Ressourcen zu bereinigen, bevor die Komponente ausgehängt wird. Dies kann erforderlich sein, um Speicherverluste zu vermeiden und die Anwendung effizienter zu machen. Dazu würden wir die Bereinigungsfunktion am Ende des Hooks zurückgeben.

 useEffect(() => { console.log('mounted') return () => console.log('unmounting... clean up here') })

Der useEffect Hook wird mounted protokolliert, wenn die Komponente gemountet wird. Unmounting… clean up here wird protokolliert, wenn die Komponente unmountet wird. Dies kann passieren, wenn die Komponente von der Benutzeroberfläche entfernt wird.

Der Bereinigungsprozess folgt normalerweise dem unten stehenden Formular.

 useEffect(() => { //The effect we intend to make effect //We then return the clean up return () => the cleanup/unsubscription })

Obwohl Sie möglicherweise nicht so viele Anwendungsfälle für useEffect Abonnements finden, ist es nützlich, wenn Sie mit Abonnements und Timern umgehen. Insbesondere beim Umgang mit Web-Sockets müssen Sie sich möglicherweise vom Netzwerk abmelden, um Ressourcen zu sparen und die Leistung zu verbessern, wenn die Komponente deaktiviert wird.

Abrufen und erneutes Abrufen von Daten mit useEffect

Einer der häufigsten Anwendungsfälle des useEffect -Hooks ist das Abrufen und Vorabrufen von Daten aus einer API.

Um dies zu veranschaulichen, verwenden wir gefälschte Benutzerdaten, die ich aus JSONPlaceholder erstellt habe, um Daten mit dem useEffect Hook abzurufen.

 import { useEffect, useState } from "react"; import axios from "axios"; export default function App() { const [users, setUsers] = useState([]); const endPoint = "https://my-json-server.typicode.com/ifeanyidike/jsondata/users"; useEffect(() => { const fetchUsers = async () => { const { data } = await axios.get(endPoint); setUsers(data); }; fetchUsers(); }, []); return ( <div className="App"> {users.map((user) => ( <div> <h2>{user.name}</h2> <p>Occupation: {user.job}</p> <p>Sex: {user.sex}</p> </div> ))} </div> ); }

Im obigen Code haben wir mithilfe des useState -Hooks einen users erstellt. Dann haben wir mit Axios Daten von einer API abgerufen. Dies ist ein asynchroner Prozess, und deshalb haben wir die async/await-Funktion verwendet, wir hätten auch den Punkt und dann die Syntax verwenden können. Da wir eine Liste von Benutzern abgerufen haben, haben wir sie einfach gemappt, um die Daten anzuzeigen.

Beachten Sie, dass wir einen leeren Parameter an den Hook übergeben haben. Dadurch wird sichergestellt, dass es nur einmal aufgerufen wird, wenn die Komponente bereitgestellt wird.

Wir können die Daten auch erneut abrufen , wenn sich einige Bedingungen ändern. Wir zeigen dies im folgenden Code.

 import { useEffect, useState } from "react"; import axios from "axios"; export default function App() { const [userIDs, setUserIDs] = useState([]); const [user, setUser] = useState({}); const [currentID, setCurrentID] = useState(1); const endPoint = "https://my-json-server.typicode.com/ifeanyidike/userdata/users"; useEffect(() => { axios.get(endPoint).then(({ data }) => setUserIDs(data)); }, []); useEffect(() => { const fetchUserIDs = async () => { const { data } = await axios.get(`${endPoint}/${currentID}`}); setUser(data); }; fetchUserIDs(); }, [currentID]); const moveToNextUser = () => { setCurrentID((prevId) => (prevId < userIDs.length ? prevId + 1 : prevId)); }; const moveToPrevUser = () => { setCurrentID((prevId) => (prevId === 1 ? prevId : prevId - 1)); }; return ( <div className="App"> <div> <h2>{user.name}</h2> <p>Occupation: {user.job}</p> <p>Sex: {user.sex}</p> </div> <button onClick={moveToPrevUser}>Prev</button> <button onClick={moveToNextUser}>Next</button> </div> ); }

Hier haben wir zwei useEffect Hooks erstellt. In der ersten haben wir die Punkt-dann-Syntax verwendet, um alle Benutzer von unserer API abzurufen. Dies ist notwendig, um die Anzahl der Benutzer zu ermitteln.

Wir haben dann einen weiteren useEffect erstellt, um einen Benutzer basierend auf der id zu erhalten. Dieser useEffect ruft die Daten immer dann neu ab, wenn sich die ID ändert. Um dies sicherzustellen, haben wir die id in der Abhängigkeitsliste übergeben.

Als Nächstes haben wir Funktionen erstellt, um den Wert unserer id zu aktualisieren, wenn auf die Schaltflächen geklickt wird. Sobald sich der Wert der id ändert, wird useEffect erneut ausgeführt und die Daten erneut abgerufen.

Wenn wir wollen, können wir sogar das Promise-basierte Token in Axios bereinigen oder stornieren, das könnten wir mit der oben besprochenen Bereinigungsmethode tun.

 useEffect(() => { const source = axios.CancelToken.source(); const fetchUsers = async () => { const { data } = await axios.get(`${endPoint}/${num}`, { cancelToken: source.token }); setUser(data); }; fetchUsers(); return () => source.cancel(); }, [num]);

Hier haben wir das Axios-Token als zweiten Parameter an axios.get . Wenn die Komponente ausgehängt wird, haben wir das Abonnement gekündigt, indem wir die Cancel-Methode des Quellobjekts aufgerufen haben.

Der useReducer Hook

Der useReducer Hook ist ein sehr nützlicher React-Hook, der etwas Ähnliches wie der useState Hook macht. Laut der React-Dokumentation sollte dieser Hook verwendet werden, um komplexere Logik zu handhaben als der useState Hook. Es ist erwähnenswert, dass der useState Hook intern mit dem useReducer-Hook implementiert wird.

Der Hook nimmt einen Reducer als Argument und kann optional den Anfangszustand und eine Init-Funktion als Argumente nehmen.

 const [state, dispatch] = useReducer(reducer, initialState, init)

Hier ist init eine Funktion und wird immer dann verwendet, wenn wir den Anfangszustand träge erstellen wollen.

Sehen wir uns an, wie Sie den useReducer -Hook implementieren, indem Sie eine einfache To-do-App erstellen, wie in der Sandbox unten gezeigt.

Todo-Beispiel

Zunächst sollten wir unseren Reduzierer erstellen, um die Zustände zu halten.

 export const ADD_TODO = "ADD_TODO"; export const REMOVE_TODO = "REMOVE_TODO"; export const COMPLETE_TODO = "COMPLETE_TODO"; const reducer = (state, action) => { switch (action.type) { case ADD_TODO: const newTodo = { id: action.id, text: action.text, completed: false }; return [...state, newTodo]; case REMOVE_TODO: return state.filter((todo) => todo.id !== action.id); case COMPLETE_TODO: const completeTodo = state.map((todo) => { if (todo.id === action.id) { return { ...todo, completed: !todo.completed }; } else { return todo; } }); return completeTodo; default: return state; } }; export default reducer;

Wir haben drei Konstanten erstellt, die unseren Aktionstypen entsprechen. Wir hätten Strings direkt verwenden können, aber diese Methode ist vorzuziehen, um Tippfehler zu vermeiden.

Dann haben wir unsere Reducer-Funktion erstellt. Wie in Redux muss der Reducer den Zustand und das Aktionsobjekt annehmen. Aber im Gegensatz zu Redux müssen wir unseren Reducer hier nicht initialisieren.

Darüber hinaus kann ein useReducer für viele Anwendungsfälle der Zustandsverwaltung zusammen mit dem über den Kontext bereitgestellten dispatch einer größeren Anwendung ermöglichen, Aktionen auszulösen, den state zu aktualisieren und darauf zu hören.

Dann haben wir die switch Anweisungen verwendet, um den vom Benutzer übergebenen Aktionstyp zu überprüfen. Wenn der Aktionstyp ADD_TODO ist, möchten wir eine neue Aufgabe übergeben, und wenn es sich um REMOVE_TODO handelt, möchten wir die Aufgaben filtern und diejenige entfernen, die der vom Benutzer übergebenen id entspricht. Wenn es sich um COMPLETE_TODO handelt, möchten wir die Aufgaben zuordnen und die mit der vom Benutzer übergebenen id umschalten.

Hier ist die App.js -Datei, in der wir den reducer implementiert haben.

 import { useReducer, useState } from "react"; import "./styles.css"; import reducer, { ADD_TODO, REMOVE_TODO, COMPLETE_TODO } from "./reducer"; export default function App() { const [id, setId] = useState(0); const [text, setText] = useState(""); const initialState = [ { id: id, text: "First Item", completed: false } ]; //We could also pass an empty array as the initial state //const initialState = [] const [state, dispatch] = useReducer(reducer, initialState); const addTodoItem = (e) => { e.preventDefault(); const newId = id + 1; setId(newId); dispatch({ type: ADD_TODO, id: newId, text: text }); setText(""); }; const removeTodo = (id) => { dispatch({ type: REMOVE_TODO, id }); }; const completeTodo = (id) => { dispatch({ type: COMPLETE_TODO, id }); }; return ( <div className="App"> <h1>Todo Example</h1> <form className="input" onSubmit={addTodoItem}> <input value={text} onChange={(e) => setText(e.target.value)} /> <button disabled={text.length === 0} type="submit">+</button> </form> <div className="todos"> {state.map((todo) => ( <div key={todo.id} className="todoItem"> <p className={todo.completed && "strikethrough"}>{todo.text}</p> <span onClick={() => removeTodo(todo.id)}>✕</span> <span onClick={() => completeTodo(todo.id)}>✓</span> </div> ))} </div> </div> ); }

Hier haben wir ein Formular erstellt, das ein Eingabeelement zum Sammeln der Eingaben des Benutzers und eine Schaltfläche zum Auslösen der Aktion enthält. Wenn das Formular gesendet wird, senden wir eine Aktion vom Typ ADD_TODO und übergeben eine neue ID und einen Aufgabentext. Wir haben eine neue ID erstellt, indem wir den vorherigen ID-Wert um 1 erhöht haben. Dann haben wir das Eingabetextfeld gelöscht. Zum Löschen und Erledigen von Aufgaben haben wir einfach die entsprechenden Aktionen abgeschickt. Diese sind wie oben dargestellt bereits im Reducer implementiert.

Die Magie geschieht jedoch, weil wir den useReducer Hook verwenden. Dieser Hook akzeptiert den Reducer und den Anfangszustand und gibt den Zustand und die Dispatch-Funktion zurück. Hier dient die Dispatch-Funktion demselben Zweck wie die Setter-Funktion für den useState Hook, und wir können sie anstelle von dispatch beliebig nennen.

Um die To-Do-Elemente anzuzeigen, haben wir einfach die Liste der To-Dos zugeordnet, die in unserem Statusobjekt zurückgegeben wurden, wie im obigen Code gezeigt.

Dies zeigt die Leistungsfähigkeit des useReducer -Hooks. Wir könnten diese Funktionalität auch mit dem useState Hook erreichen, aber wie Sie im obigen Beispiel sehen können, hat uns der useReducer Hook geholfen, die Dinge übersichtlicher zu halten. useReducer ist oft von Vorteil, wenn das Zustandsobjekt eine komplexe Struktur ist und im Gegensatz zu einem einfachen Wertersatz auf unterschiedliche Weise aktualisiert wird. Sobald diese Update-Funktionen komplizierter werden, macht es useReducer einfach, all diese Komplexität in einer Reducer-Funktion (die eine reine JS-Funktion ist) zu halten, wodurch es sehr einfach ist, Tests nur für die Reducer-Funktion zu schreiben.

Wir hätten auch das dritte Argument an den useReducer Hook übergeben können, um den Anfangszustand träge zu erstellen. Das bedeutet, dass wir den Anfangszustand in einer init -Funktion berechnen könnten.

Zum Beispiel könnten wir eine init -Funktion wie folgt erstellen:

 const initFunc = () => [ { id: id, text: "First Item", completed: false } ]

und übergeben Sie es dann an unseren useReducer Hook.

 const [state, dispatch] = useReducer(reducer, initialState, initFunc)

Wenn wir dies tun, überschreibt die initFunc den von uns bereitgestellten initialState und der anfängliche Zustand wird träge berechnet.

Der useContext Hook

Die React Context API bietet eine Möglichkeit, Zustände oder Daten im gesamten React-Komponentenbaum zu teilen. Die API war in React als experimentelles Feature für eine Weile verfügbar, aber in React 16.3.0 wurde es sicher, sie zu verwenden. Die API erleichtert den Datenaustausch zwischen Komponenten und eliminiert Prop Drilling.

Während Sie den React Context auf Ihre gesamte Anwendung anwenden können, ist es auch möglich, ihn auf einen Teil der Anwendung anzuwenden.

Um den Hook zu verwenden, müssen Sie zuerst einen Kontext mit React.createContext und dieser Kontext kann dann an den Hook übergeben werden.

Um die Verwendung des useContext -Hooks zu demonstrieren, erstellen wir eine einfache App, die die Schriftgröße in unserer gesamten Anwendung erhöht.

Lassen Sie uns unseren Kontext in der Datei context.js erstellen.

 import { createContext } from "react"; //Here, we set the initial fontSize as 16. const fontSizeContext = createContext(16); export default fontSizeContext;

Hier haben wir einen Kontext erstellt und ihm einen Anfangswert von 16 übergeben und dann den Kontext exportiert. Als Nächstes verbinden wir unseren Kontext mit unserer Anwendung.

 import FontSizeContext from "./context"; import { useState } from "react"; import PageOne from "./PageOne"; import PageTwo from "./PageTwo"; const App = () => { const [size, setSize] = useState(16); return ( <FontSizeContext.Provider value={size}> <PageOne /> <PageTwo /> <button onClick={() => setSize(size + 5)}>Increase font</button> <button onClick={() => setSize((prevSize) => Math.min(11, prevSize - 5)) } > Decrease font </button> </FontSizeContext.Provider> ); }; export default App;

Im obigen Code haben wir unseren gesamten Komponentenbaum mit FontSizeContext.Provider und size an seinen Wertprop übergeben. Hier ist size ein Zustand, der mit dem useState -Hook erstellt wird. Dies ermöglicht es uns, den Wertprop zu ändern, wenn sich der size ändert. Indem wir die gesamte Komponente mit dem Provider , können wir überall in unserer Anwendung auf den Kontext zugreifen.

Beispielsweise haben wir auf den Kontext in <PageOne /> und <PageTwo /> . Infolgedessen erhöht sich die Schriftgröße über diese beiden Komponenten hinweg, wenn wir sie aus der App.js -Datei erhöhen. Wir können die Schriftgröße über die oben gezeigten Schaltflächen erhöhen oder verringern, und sobald wir dies tun, ändert sich die Schriftgröße in der gesamten Anwendung.

 import { useContext } from "react"; import context from "./context"; const PageOne = () => { const size = useContext(context); return <p style={{ fontSize: `${size}px` }}>Content from the first page</p>; }; export default PageOne;

Hier haben wir mit dem useContext Hook unserer PageOne -Komponente auf den Kontext zugegriffen. Wir haben dann diesen Kontext verwendet, um unsere Schriftgrößeneigenschaft festzulegen. Ein ähnliches Verfahren gilt für die Datei PageTwo.js .

Designs oder andere übergeordnete Konfigurationen auf App-Ebene sind gute Kandidaten für Kontexte.

Verwenden useContext und useReducer

Bei Verwendung mit dem useReducer Hook ermöglicht uns useContext , unser eigenes Zustandsverwaltungssystem zu erstellen. Wir können globale Zustände erstellen und diese einfach in unserer Anwendung verwalten.

Lassen Sie uns unsere Aufgabenanwendung mithilfe der Kontext-API verbessern.

Wie üblich müssen wir einen todoContext in der Datei todoContext.js erstellen.

 import { createContext } from "react"; const initialState = []; export default createContext(initialState);

Hier haben wir den Kontext erstellt und einen Anfangswert eines leeren Arrays übergeben. Dann haben wir den Kontext exportiert.

Lassen Sie uns unsere App.js -Datei umgestalten, indem wir die Aufgabenliste und die Elemente trennen.

 import { useReducer, useState } from "react"; import "./styles.css"; import todoReducer, { ADD_TODO } from "./todoReducer"; import TodoContext from "./todoContext"; import TodoList from "./TodoList"; export default function App() { const [id, setId] = useState(0); const [text, setText] = useState(""); const initialState = []; const [todoState, todoDispatch] = useReducer(todoReducer, initialState); const addTodoItem = (e) => { e.preventDefault(); const newId = id + 1; setId(newId); todoDispatch({ type: ADD_TODO, id: newId, text: text }); setText(""); }; return ( <TodoContext.Provider value={[todoState, todoDispatch]}> <div className="app"> <h1>Todo Example</h1> <form className="input" onSubmit={addTodoItem}> <input value={text} onChange={(e) => setText(e.target.value)} /> <button disabled={text.length === 0} type="submit"> + </button> </form> <TodoList /> </div> </TodoContext.Provider> ); }

Hier haben wir unsere App.js -Datei mit TodoContext.Provider und dann die Rückgabewerte unseres todoReducer an sie übergeben. Dadurch sind der Status und dispatch -Funktion des Reducers in unserer gesamten Anwendung zugänglich.

Anschließend haben wir die To-Do-Anzeige in eine Komponente TodoList . Dank der Context-API haben wir dies ohne Prop Drilling geschafft. Werfen wir einen Blick auf die Datei TodoList.js .

 import React, { useContext } from "react"; import TodoContext from "./todoContext"; import Todo from "./Todo"; const TodoList = () => { const [state] = useContext(TodoContext); return ( <div className="todos"> {state.map((todo) => ( <Todo key={todo.id} todo={todo} /> ))} </div> ); }; export default TodoList;

Unter Verwendung der Array-Destrukturierung können wir mithilfe des useContext aus dem Kontext auf den Zustand zugreifen (wobei wir die Dispatch-Funktion verlassen). Wir können dann den Zustand durchgehen und die zu erledigenden Punkte anzeigen. Wir haben dies noch in einer Todo Komponente extrahiert. Die ES6+-Kartenfunktion erfordert, dass wir einen eindeutigen Schlüssel übergeben, und da wir die spezifische Aufgabe benötigen, übergeben wir sie auch nebenher.

Werfen wir einen Blick auf die Todo -Komponente.

 import React, { useContext } from "react"; import TodoContext from "./todoContext"; import { REMOVE_TODO, COMPLETE_TODO } from "./todoReducer"; const Todo = ({ todo }) => { const [, dispatch] = useContext(TodoContext); const removeTodo = (id) => { dispatch({ type: REMOVE_TODO, id }); }; const completeTodo = (id) => { dispatch({ type: COMPLETE_TODO, id }); }; return ( <div className="todoItem"> <p className={todo.completed ? "strikethrough" : "nostrikes"}> {todo.text} </p> <span onClick={() => removeTodo(todo.id)}>✕</span> <span onClick={() => completeTodo(todo.id)}>✓</span> </div> ); }; export default Todo;

Wieder unter Verwendung der Array-Destrukturierung haben wir aus dem Kontext auf die Dispatch-Funktion zugegriffen. Dadurch können wir die Funktionen completeTodo und removeTodo definieren, wie bereits im Abschnitt useReducer besprochen. Mit der von todo übergebenen Todo-Prop können wir ein todoList.js -do-Element anzeigen. Wir können es auch als abgeschlossen markieren und die Aufgabe entfernen, wenn wir dies für angebracht halten.

Es ist auch möglich, mehr als einen Kontextanbieter im Stamm unserer Anwendung zu verschachteln. Das bedeutet, dass wir mehr als einen Kontext verwenden können, um verschiedene Funktionen in einer Anwendung auszuführen.

Um dies zu demonstrieren, fügen wir dem Aufgabenbeispiel ein Thema hinzu.

Hier ist, was wir bauen werden.

Auch hier müssen wir themeContext erstellen. Erstellen Sie dazu eine themeContext.js -Datei und fügen Sie die folgenden Codes hinzu.

 import { createContext } from "react"; import colors from "./colors"; export default createContext(colors.light);

Hier haben wir einen Kontext erstellt und colors.light als Anfangswert übergeben. Lassen Sie uns die Farben mit dieser Eigenschaft in der Datei colors.js definieren.

 const colors = { light: { backgroundColor: "#fff", color: "#000" }, dark: { backgroundColor: "#000", color: "#fff" } }; export default colors;

Im obigen Code haben wir ein colors erstellt, das helle und dunkle Eigenschaften enthält. Jede Eigenschaft hat ein backgroundColor und ein color .

Als Nächstes erstellen wir den themeReducer , um die Designzustände zu verarbeiten.

 import Colors from "./colors"; export const LIGHT = "LIGHT"; export const DARK = "DARK"; const themeReducer = (state, action) => { switch (action.type) { case LIGHT: return { ...Colors.light }; case DARK: return { ...Colors.dark }; default: return state; } }; export default themeReducer;

Wie alle Reducer übernimmt der themeReducer den Zustand und die Aktion. Anschließend verwendet es die switch Anweisung, um die aktuelle Aktion zu bestimmen. Wenn es vom Typ LIGHT ist, weisen wir einfach Requisiten Colors.light und wenn es vom Typ DARK ist, zeigen wir Requisiten Colors.dark . Wir hätten dies leicht mit dem useState Hook tun können, aber wir wählen useReducer , um den Punkt nach Hause zu bringen.

Nachdem wir den themeReducer eingerichtet haben, können wir ihn dann in unsere App.js -Datei integrieren.

 import { useReducer, useState, useCallback } from "react"; import "./styles.css"; import todoReducer, { ADD_TODO } from "./todoReducer"; import TodoContext from "./todoContext"; import ThemeContext from "./themeContext"; import TodoList from "./TodoList"; import themeReducer, { DARK, LIGHT } from "./themeReducer"; import Colors from "./colors"; import ThemeToggler from "./ThemeToggler"; const themeSetter = useCallback( theme => themeDispatch({type: theme}, [themeDispatch]); export default function App() { const [id, setId] = useState(0); const [text, setText] = useState(""); const initialState = []; const [todoState, todoDispatch] = useReducer(todoReducer, initialState); const [themeState, themeDispatch] = useReducer(themeReducer, Colors.light); const themeSetter = useCallback( (theme) => { themeDispatch({ type: theme }); }, [themeDispatch] ); const addTodoItem = (e) => { e.preventDefault(); const newId = id + 1; setId(newId); todoDispatch({ type: ADD_TODO, id: newId, text: text }); setText(""); }; return ( <TodoContext.Provider value={[todoState, todoDispatch]}> <ThemeContext.Provider value={[ themeState, themeSetter ]} > <div className="app" style={{ ...themeState }}> <ThemeToggler /> <h1>Todo Example</h1> <form className="input" onSubmit={addTodoItem}> <input value={text} onChange={(e) => setText(e.target.value)} /> <button disabled={text.length === 0} type="submit"> + </button> </form> <TodoList /> </div> </ThemeContext.Provider> </TodoContext.Provider> ); }

Im obigen Code haben wir unserer bereits vorhandenen To-Do-Anwendung einige Dinge hinzugefügt. Wir begannen mit dem Importieren von ThemeContext , themeReducer , ThemeToggler und Colors . We created a reducer using the useReducer hook, passing the themeReducer and an initial value of Colors.light to it. This returned the themeState and themeDispatch to us.

We then nested our component with the provider function from the ThemeContext , passing the themeState and the dispatch functions to it. We also added theme styles to it by spreading out the themeStates . This works because the colors object already defined properties similar to what the JSX styles will accept.

However, the actual theme toggling happens in the ThemeToggler component. Werfen wir einen Blick darauf.

 import ThemeContext from "./themeContext"; import { useContext, useState } from "react"; import { DARK, LIGHT } from "./themeReducer"; const ThemeToggler = () => { const [showLight, setShowLight] = useState(true); const [themeState, themeSetter] = useContext(ThemeContext); const dispatchDarkTheme = () => themeSetter(DARK); const dispatchLightTheme = () => themeSetter(LIGHT); const toggleTheme = () => { showLight ? dispatchDarkTheme() : dispatchLightTheme(); setShowLight(!showLight); }; console.log(themeState); return ( <div> <button onClick={toggleTheme}> {showLight ? "Change to Dark Theme" : "Change to Light Theme"} </button> </div> ); }; export default ThemeToggler;

In this component, we used the useContext hook to retrieve the values we passed to the ThemeContext.Provider from our App.js file. As shown above, these values include the ThemeState , dispatch function for the light theme, and dispatch function for the dark theme. Thereafter, we simply called the dispatch functions to toggle the themes. We also created a state showLight to determine the current theme. This allows us to easily change the button text depending on the current theme.

The useMemo Hook

The useMemo hook is designed to memoize expensive computations. Memoization simply means caching. It caches the computation result with respect to the dependency values so that when the same values are passed, useMemo will just spit out the already computed value without recomputing it again. This can significantly improve performance when done correctly.

The hook can be used as follows:

 const memoizedResult = useMemo(() => expensiveComputation(a, b), [a, b])

Let's consider three cases of the useMemo hook.

  1. When the dependency values, a and b remain the same.
    The useMemo hook will return the already computed memoized value without recomputation.
  2. When the dependency values, a and b change.
    The hook will recompute the value.
  3. When no dependency value is passed.
    The hook will recompute the value.

Let's take a look at an example to demonstrate this concept.

In the example below, we'll be computing the PAYE and Income after PAYE of a company's employees with fake data from JSONPlaceholder.

The calculation will be based on the personal income tax calculation procedure for Nigeria providers by PricewaterhouseCoopers available here.

This is shown in the sandbox below.

First, we queried the API to get the employees' data. We also get data for each employee (with respect to their employee id).

const [employee, setEmployee] = useState({}); const [employees, setEmployees] = useState([]); const [num, setNum] = useState(1); const endPoint = "https://my-json-server.typicode.com/ifeanyidike/jsondata/employees"; useEffect(() => { const getEmployee = async () => { const { data } = await axios.get(`${endPoint}/${num}`); setEmployee(data); }; getEmployee(); }, [num]); useEffect(() => { axios.get(endPoint).then(({ data }) => setEmployees(data)); }, [num]);

Wir axios und die async/await -Methode im ersten useEffect und dann die Punkt-dann-Syntax im zweiten verwendet. Diese beiden Ansätze funktionieren auf die gleiche Weise.

Als nächstes berechnen wir anhand der oben erhaltenen Mitarbeiterdaten die Entlastungsvariablen:

 const taxVariablesCompute = useMemo(() => { const { income, noOfChildren, noOfDependentRelatives } = employee; //supposedly complex calculation //tax relief computations for relief Allowance, children relief, // relatives relief and pension relief const reliefs = reliefAllowance1 + reliefAllowance2 + childrenRelief + relativesRelief + pensionRelief; return reliefs; }, [employee]);

Dies ist eine ziemlich komplexe Berechnung, und deshalb mussten wir sie in einen useMemo Hook packen, um sie zu speichern oder zu optimieren. Wenn Sie es auf diese Weise auswendig lernen, wird sichergestellt, dass die Berechnung nicht neu berechnet wird, wenn wir erneut versuchen, auf denselben Mitarbeiter zuzugreifen.

Darüber hinaus möchten wir anhand der oben erhaltenen Steuerentlastungswerte das PAYE und das Einkommen nach PAYE berechnen.

 const taxCalculation = useMemo(() => { const { income } = employee; let taxableIncome = income - taxVariablesCompute; let PAYE = 0; //supposedly complex calculation //computation to compute the PAYE based on the taxable income and tax endpoints const netIncome = income - PAYE; return { PAYE, netIncome }; }, [employee, taxVariablesCompute]);

Wir haben die Steuerberechnung (eine ziemlich komplexe Berechnung) unter Verwendung der oben berechneten Steuervariablen durchgeführt und sie dann mit dem useMemo Hook gespeichert.

Den vollständigen Code finden Sie hier.

Dies folgt dem hier angegebenen Steuerberechnungsverfahren. Wir haben zunächst den Steuerfreibetrag unter Berücksichtigung des Einkommens, der Kinderzahl und der Zahl der unterhaltsberechtigten Angehörigen berechnet. Anschließend multiplizierten wir das steuerpflichtige Einkommen schrittweise mit den PIT-Sätzen. Obwohl die fragliche Berechnung für dieses Tutorial nicht unbedingt erforderlich ist, wird sie bereitgestellt, um uns zu zeigen, warum useMemo möglicherweise erforderlich ist. Dies ist auch eine ziemlich komplexe Berechnung, und daher müssen wir sie möglicherweise wie oben gezeigt mit useMemo auswendig lernen.

Nach der Berechnung der Werte haben wir das Ergebnis einfach angezeigt.

Beachten Sie Folgendes zum useMemo Hook.

  • useMemo sollte nur verwendet werden, wenn es notwendig ist, die Berechnung zu optimieren. Mit anderen Worten, wenn die Neuberechnung teuer ist.
  • Es ist ratsam, die Berechnung zunächst ohne Auswendiglernen zu schreiben und nur dann auswendig zu lernen, wenn dies zu Leistungsproblemen führt.
  • Unnötige und irrelevante Verwendung des useMemo kann die Leistungsprobleme sogar noch verstärken.
  • Manchmal kann auch zu viel Merken zu Leistungsproblemen führen.

Der useCallback Hook

useCallback den gleichen Zweck wie useMemo , gibt aber einen gespeicherten Callback anstelle eines gespeicherten Werts zurück. Mit anderen Worten, useCallback ist dasselbe wie useMemo ohne Funktionsaufruf zu übergeben.

Betrachten Sie beispielsweise die folgenden Codes unten.

 import React, {useCallback, useMemo} from 'react' const MemoizationExample = () => { const a = 5 const b = 7 const memoResult = useMemo(() => a + b, [a, b]) const callbackResult = useCallback(a + b, [a, b]) console.log(memoResult) console.log(callbackResult) return( <div> ... </div> ) } export default MemoizationExample

Im obigen Beispiel geben sowohl memoResult als auch callbackResult denselben Wert von 12 . Hier gibt useCallback einen gespeicherten Wert zurück. Wir könnten es jedoch auch dazu bringen, einen gespeicherten Rückruf zurückzugeben, indem wir es als Funktion übergeben.

Der useCallback unten gibt einen gespeicherten Callback zurück.

 ... const callbackResult = useCallback(() => a + b, [a, b]) ...

Wir können den Callback dann auslösen, wenn eine Aktion ausgeführt wird oder in einem useEffect Hook.

 import {useCallback, useEffect} from 'react' const memoizationExample = () => { const a = 5 const b = 7 const callbackResult = useCallback(() => a + b, [a, b]) useEffect(() => { const callback = callbackResult() console.log(callback) }) return ( <div> <button onClick= {() => console.log(callbackResult())}> Trigger Callback </button> </div> ) } export default memoizationExample

Im obigen Code haben wir eine Callback-Funktion mit dem useCallback Hook definiert. Wir haben dann den Callback in einem useEffect Hook aufgerufen, wenn die Komponente gemountet wird und auch wenn auf eine Schaltfläche geklickt wird.

Sowohl der useEffect als auch der Button-Klick führen zum gleichen Ergebnis.

Beachten Sie, dass die Konzepte, Gebote und Verbote, die für den useMemo Hook gelten, auch für den useCallback -Hook gelten. Wir können das useMemo Beispiel mit useCallback .

Der useRef Hook

useRef gibt ein Objekt zurück, das in einer Anwendung bestehen bleiben kann. Der Hook hat nur eine Eigenschaft, current , und wir können ihm leicht ein Argument übergeben.

Es dient demselben Zweck createRef , das in klassenbasierten Komponenten verwendet wird. Wir können mit diesem Hook wie folgt eine Referenz erstellen:

 const newRef = useRef('')

Hier haben wir eine neue Referenz namens newRef und ihr eine leere Zeichenfolge übergeben.

Dieser Haken wird hauptsächlich für zwei Zwecke verwendet:

  1. Zugriff auf oder Manipulation des DOM und
  2. Veränderliche Zustände speichern – dies ist nützlich, wenn wir nicht möchten, dass die Komponente neu gerendert wird, wenn sich ein Wert ändert.

Manipulation des DOM

Wenn es an ein DOM-Element übergeben wird, zeigt das ref-Objekt auf dieses Element und kann verwendet werden, um auf seine DOM-Attribute und -Eigenschaften zuzugreifen.

Hier ist ein sehr einfaches Beispiel, um dieses Konzept zu demonstrieren.

 import React, {useRef, useEffect} from 'react' const RefExample = () => { const headingRef = useRef('') console.log(headingRef) return( <div> <h1 className='topheading' ref={headingRef}>This is a h1 element</h1> </div> ) } export default RefExample

Im obigen Beispiel haben wir headingRef mithilfe des Hooks „ useRef definiert, der eine leere Zeichenfolge übergibt. Wir setzen dann die Referenz im h1 -Tag, indem wir ref = {headingRef} . Indem wir diese Referenz setzen, haben wir die headingRef gebeten, auf unser h1 -Element zu zeigen. Das bedeutet, dass wir über die Referenz auf die Eigenschaften unseres h1 Elements zugreifen können.

Um dies zu sehen, erhalten wir, wenn wir den Wert von console.log(headingRef) überprüfen, {current: HTMLHeadingElement} oder {current: h1} und wir können alle Eigenschaften oder Attribute des Elements bewerten. Ähnliches gilt für jedes andere HTML-Element.

Zum Beispiel könnten wir den Text kursiv machen, wenn die Komponente montiert wird.

 useEffect(() => { headingRef.current.style.font; }, []);

Wir können den Text sogar in etwas anderes ändern.

 ... headingRef.current.innerHTML = "A Changed H1 Element"; ...

Wir können sogar die Hintergrundfarbe des übergeordneten Containers ändern.

 ... headingRef.current.parentNode.style.backgroundColor = "red"; ...

Hier kann jede Art von DOM-Manipulation durchgeführt werden. Beachten Sie, dass headingRef.current genauso gelesen werden kann wie document.querySelector('.topheading') .

Ein interessanter Anwendungsfall des useRef bei der Bearbeitung des DOM-Elements besteht darin, den Cursor auf das Eingabeelement zu fokussieren. Lass es uns schnell durchgehen.

 import {useRef, useEffect} from 'react' const inputRefExample = () => { const inputRef = useRef(null) useEffect(() => { inputRef.current.focus() }, []) return( <div> <input ref={inputRef} /> <button onClick = {() => inputRef.current.focus()}>Focus on Input </button> </div> ) } export default inputRefExample

Im obigen Code haben wir inputRef mit dem useRef Hook erstellt und ihn dann gebeten, auf das Eingabeelement zu zeigen. Wir haben dann den Cursor auf die Eingabereferenz fokussiert, wenn die Komponente geladen wird und wenn auf die Schaltfläche geklickt wird, indem inputRef.current.focus() verwenden. Dies ist möglich, weil focus() ein Attribut von Eingabeelementen ist und somit der Schiedsrichter die Methoden beurteilen kann.

Refs, die in einer übergeordneten Komponente erstellt wurden, können an der untergeordneten Komponente bewertet werden, indem sie mit React.forwardRef() werden. Werfen wir einen Blick darauf.

Lassen Sie uns zunächst eine weitere Komponente NewInput.js erstellen und ihr die folgenden Codes hinzufügen.

 import { useRef, forwardRef } from "react"; const NewInput = forwardRef((props, ref) => { return <input placeholder={props.val} ref={ref} />; }); export default NewInput;

Diese Komponente akzeptiert props und ref . Wir haben die ref an ihre ref-Prop und props.val an ihre Platzhalter-Prop übergeben. Reguläre React-Komponenten nehmen kein ref Attribut. Dieses Attribut ist nur verfügbar, wenn wir es wie oben gezeigt mit React.forwardRef .

Wir können dies dann einfach in der übergeordneten Komponente aufrufen.

 ... <NewInput val="Just an example" ref={inputRef} /> ...

Speichern der änderbaren Zustände

Refs werden nicht nur verwendet, um DOM-Elemente zu manipulieren, sie können auch verwendet werden, um veränderliche Werte zu speichern, ohne die gesamte Komponente neu zu rendern.

Das folgende Beispiel erkennt, wie oft auf eine Schaltfläche geklickt wird, ohne die Komponente erneut zu rendern.

 import { useRef } from "react"; export default function App() { const countRef = useRef(0); const increment = () => { countRef.current++; console.log(countRef); }; return ( <div className="App"> <button onClick={increment}>Increment </button> </div> ); }

Im obigen Code haben wir den countRef wenn auf die Schaltfläche geklickt wird, und ihn dann in der Konsole protokolliert. Obwohl der Wert wie in der Konsole angezeigt erhöht wird, können wir keine Änderung feststellen, wenn wir versuchen, ihn direkt in unserer Komponente zu bewerten. Es wird nur in der Komponente aktualisiert, wenn es erneut gerendert wird.

Beachten Sie, dass useState zwar asynchron ist, useRef jedoch synchron ist. Mit anderen Worten, der Wert ist sofort verfügbar, nachdem er aktualisiert wurde.

Der useLayoutEffect Hook

Wie der useEffect Hook wird useLayoutEffect aufgerufen, nachdem die Komponente gemountet und gerendert wurde. Dieser Hook wird nach einer DOM-Mutation ausgelöst, und zwar synchron. Abgesehen davon, dass useLayoutEffect nach der DOM-Mutation synchron aufgerufen wird, macht es dasselbe wie useEffect .

useLayoutEffect sollte nur zur Durchführung von DOM-Mutationen oder DOM-bezogenen Messungen verwendet werden, andernfalls sollten Sie den useEffect Hook verwenden. Die Verwendung des useEffect für DOM-Mutationsfunktionen kann einige Leistungsprobleme wie Flackern verursachen, aber useLayoutEffect behandelt sie perfekt, wenn es ausgeführt wird, nachdem die Mutationen aufgetreten sind.

Sehen wir uns einige Beispiele an, um dieses Konzept zu demonstrieren.

  1. Wir erhalten die Breite und Höhe des Fensters bei der Größenänderung.
 import {useState, useLayoutEffect} from 'react' const ResizeExample = () =>{ const [windowSize, setWindowSize] = useState({width: 0, height: 0}) useLayoutEffect(() => { const resizeWindow = () => setWindowSize({ width: window.innerWidth, height: window.innerHeight }) window.addEventListener('resize', resizeWindow) return () => window.removeEventListener('resize', resizeWindow) }, []) return ( <div> <p>width: {windowSize.width}</p> <p>height: {windowSize.height}</p> </div> ) } export default ResizeExample

Im obigen Code haben wir einen Zustand windowSize mit den Eigenschaften width und height erstellt. Dann setzen wir den Status auf die Breite bzw. Höhe des aktuellen Fensters, wenn die Größe des Fensters geändert wird. Wir haben auch den Code beim Unmounten bereinigt. Der Bereinigungsprozess ist in useLayoutEffect , um die DOM-Manipulation zu bereinigen und die Effizienz zu verbessern.

  1. Lassen Sie uns einen Text mit useLayoutEffect verwischen.
 import { useRef, useState, useLayoutEffect } from "react"; export default function App() { const paragraphRef = useRef(""); useLayoutEffect(() => { const { current } = paragraphRef; const blurredEffect = () => { current.style.color = "transparent"; current.style.textShadow = "0 0 5px rgba(0,0,0,0.5)"; }; current.addEventListener("click", blurredEffect); return () => current.removeEventListener("click", blurredEffect); }, []); return ( <div className="App"> <p ref={paragraphRef}>This is the text to blur</p> </div> ); }

Wir useRef und useLayoutEffect zusammen im obigen Code verwendet. Wir haben zuerst eine Referenz, paragraphRef, erstellt, um auf unseren paragraphRef zu verweisen. Dann haben wir einen On-Click-Ereignis-Listener erstellt, um zu überwachen, wann auf den Absatz geklickt wird, und ihn dann mit den von uns definierten Stileigenschaften unkenntlich gemacht. Schließlich haben wir den Ereignis-Listener mit removeEventListener .

Die useDispatch und useSelector Hooks

useDispatch ist ein Redux-Hook zum Verteilen (Auslösen) von Aktionen in einer Anwendung. Es nimmt ein Aktionsobjekt als Argument und ruft die Aktion auf. useDispatch ist die Entsprechung des Hooks zu mapDispatchToProps .

Auf der anderen Seite ist useSelector ein Redux-Hook zur Bewertung von Redux-Zuständen. Es dauert eine Funktion, um den genauen Redux-Reduzierer aus dem Speicher auszuwählen, und gibt dann die entsprechenden Zustände zurück.

Sobald unser Redux-Speicher über den Redux-Anbieter mit einer React-Anwendung verbunden ist, können wir die Aktionen mit useDispatch und mit useSelector auf die Zustände useSelector . Mit diesen beiden Haken kann jede Redux-Aktion und jeder Zustand bewertet werden.

Beachten Sie, dass diese Zustände mit React Redux geliefert werden (ein Paket, das die Bewertung des Redux-Speichers in einer React-Anwendung vereinfacht). Sie sind in der zentralen Redux-Bibliothek nicht verfügbar.

Diese Haken sind sehr einfach zu bedienen. Zuerst müssen wir die Versandfunktion deklarieren und dann auslösen.

 import {useDispatch, useSelector} from 'react-redux' import {useEffect} from 'react' const myaction from '...' const ReduxHooksExample = () =>{ const dispatch = useDispatch() useEffect(() => { dispatch(myaction()); //alternatively, we can do this dispatch({type: 'MY_ACTION_TYPE'}) }, []) const mystate = useSelector(state => state.myReducerstate) return( ... ) } export default ReduxHooksExample

Im obigen Code importierten wir useDispatch und useSelector aus respond react-redux . Dann haben wir in einem useEffect Hook die Aktion abgeschickt. Wir könnten die Aktion in einer anderen Datei definieren und sie dann hier aufrufen oder wir könnten sie direkt definieren, wie im useEffect -Aufruf gezeigt.

Sobald wir die Aktionen versendet haben, stehen unsere Staaten zur Verfügung. Wir können dann den Status mit dem useSelector Hook wie gezeigt abrufen. Die Zustände können auf die gleiche Weise verwendet werden, wie wir Zustände aus dem useState Hook verwenden würden.

Schauen wir uns ein Beispiel an, um diese beiden Hooks zu demonstrieren.

Um dieses Konzept zu demonstrieren, müssen wir einen Redux-Speicher, einen Reducer und Aktionen erstellen. Um die Dinge hier zu vereinfachen, verwenden wir die Redux Toolkit-Bibliothek mit unserer gefälschten Datenbank von JSONPlaceholder.

Wir müssen die folgenden Pakete installieren, um loszulegen. Führen Sie die folgenden Bash-Befehle aus.

 npm i redux @reduxjs/toolkit react-redux axios

Lassen Sie uns zunächst die Datei „EmployeesSlice.js“ erstellen, um den Reducer und die Aktion für die API unserer employeesSlice.js zu handhaben.

 import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; import axios from "axios"; const endPoint = "https://my-json-server.typicode.com/ifeanyidike/jsondata/employees"; export const fetchEmployees = createAsyncThunk("employees/fetchAll", async () => { const { data } = await axios.get(endPoint); return data; }); const employeesSlice = createSlice({ name: "employees", initialState: { employees: [], loading: false, error: "" }, reducers: {}, extraReducers: { [fetchEmployees.pending]: (state, action) => { state.status = "loading"; }, [fetchEmployees.fulfilled]: (state, action) => { state.status = "success"; state.employees = action.payload; }, [fetchEmployees.rejected]: (state, action) => { state.status = "error"; state.error = action.error.message; } } }); export default employeesSlice.reducer;

Dies ist das Standard-Setup für das Redux-Toolkit. Wir createAsyncThunk verwendet, um auf die Thunk -Middleware zuzugreifen, um asynchrone Aktionen auszuführen. Dadurch konnten wir die Liste der Mitarbeiter aus der API abrufen. Anschließend haben wir das employeesSlice erstellt und je nach Aktionstyp „loading“, „error“ und die Daten der Mitarbeiter zurückgegeben.

Das Redux-Toolkit erleichtert auch die Einrichtung des Shops. Hier ist der Laden.

 import { configureStore } from "@reduxjs/toolkit"; import { combineReducers } from "redux"; import employeesReducer from "./employeesSlice"; const reducer = combineReducers({ employees: employeesReducer }); export default configureStore({ reducer });;

Hier haben wir combineReducers verwendet, um die Reducer zu bündeln, und die vom Redux-Toolkit bereitgestellte configureStore -Funktion, um den Store einzurichten.

Lassen Sie uns damit fortfahren, dies in unserer Anwendung zu verwenden.

Zuerst müssen wir Redux mit unserer React-Anwendung verbinden. Idealerweise sollte dies an der Wurzel unserer Anwendung erfolgen. Ich mache das gerne in der Datei index.js .

 import React, { StrictMode } from "react"; import ReactDOM from "react-dom"; import store from "./redux/store"; import { Provider } from "react-redux"; import App from "./App"; const rootElement = document.getElementById("root"); ReactDOM.render( <Provider store={store}> <StrictMode> <App /> </StrictMode> </Provider>, rootElement );

Hier habe ich den Store, den ich oben erstellt habe, und auch den Provider von react-redux importiert.

Dann habe ich die gesamte Anwendung mit der Provider -Funktion umschlossen und den Store an sie übergeben. Dadurch wird der Store in unserer gesamten Anwendung zugänglich.

Wir können dann mit der Verwendung der useDispatch und useSelector Hooks fortfahren, um die Daten abzurufen.

Lassen Sie uns dies in unserer App.js -Datei tun.

 import { useDispatch, useSelector } from "react-redux"; import { fetchEmployees } from "./redux/employeesSlice"; import { useEffect } from "react"; export default function App() { const dispatch = useDispatch(); useEffect(() => { dispatch(fetchEmployees()); }, [dispatch]); const employeesState = useSelector((state) => state.employees); const { employees, loading, error } = employeesState; return ( <div className="App"> {loading ? ( "Loading..." ) : error ? ( <div>{error}</div> ) : ( <> <h1>List of Employees</h1> {employees.map((employee) => ( <div key={employee.id}> <h3>{`${employee.firstName} ${employee.lastName}`}</h3> </div> ))} </> )} </div> ); }

Im obigen Code haben wir den useDispatch Hook verwendet, um die Aktion fetchEmployees “ aufzurufen, die in der Datei „ employeesSlice.js “ erstellt wurde. Dadurch wird der Mitarbeiterstatus in unserer Anwendung verfügbar. Dann haben wir den useSelector Hook verwendet, um die Zustände abzurufen. Danach haben wir die Ergebnisse durch Mapping durch die employees angezeigt.

Der useHistory Hook

Navigation ist in einer React-Anwendung sehr wichtig. Während Sie dies auf verschiedene Arten erreichen können, bietet React Router eine einfache, effiziente und beliebte Möglichkeit, dynamisches Routing in einer React-Anwendung zu erreichen. Darüber hinaus bietet React Router einige Hooks zum Bewerten des Zustands des Routers und zum Durchführen der Navigation im Browser, aber um sie zu verwenden, müssen Sie zuerst Ihre Anwendung richtig einrichten.

Um einen beliebigen React-Router-Hook zu verwenden, sollten wir unsere Anwendung zuerst mit BrowserRouter . Wir können die Routen dann mit Switch und Route verschachteln.

Aber zuerst müssen wir das Paket installieren, indem wir die folgenden Befehle ausführen.

 npm install react-router-dom

Dann müssen wir unsere Anwendung wie folgt einrichten. Ich mache das gerne in meiner App.js -Datei.

 import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; import Employees from "./components/Employees"; export default function App() { return ( <div className="App"> <Router> <Switch> <Route path='/'> <Employees /> </Route> ... </Switch> </Router> </div> ); }

Wir könnten so viele Routen wie möglich haben, abhängig von der Anzahl der Komponenten, die wir rendern möchten. Hier haben wir nur die Employees Komponente gerendert. Das path teilt React Router DOM den Pfad der Komponente mit und kann mit einer Abfragezeichenfolge oder verschiedenen anderen Methoden bewertet werden.

Hier kommt es auf die Reihenfolge an. Die Root-Route sollte unterhalb der Child-Route platziert werden und so weiter. Um diese Reihenfolge zu überschreiben, müssen Sie das exact Schlüsselwort in die Root-Route einfügen.

 <Route path='/' exact > <Employees /> </Route>

Nachdem wir den Router eingerichtet haben, können wir den useHistory Hook und andere React-Router-Hooks in unserer Anwendung verwenden.

Um den useHistory Hook zu verwenden, müssen wir ihn zuerst wie folgt deklarieren.

 import {useHistory} from 'history' import {useHistory} from 'react-router-dom' const Employees = () =>{ const history = useHistory() ... }

Wenn wir den Verlauf in der Konsole protokollieren, sehen wir mehrere damit verbundene Eigenschaften. Dazu gehören block , createHref , go , goBack , goForward , length , listen , location , push , replace . Obwohl alle diese Eigenschaften nützlich sind, werden Sie höchstwahrscheinlich history.push und history.replace häufiger verwenden als andere Eigenschaften.

Lassen Sie uns diese Eigenschaft verwenden, um von einer Seite zur anderen zu wechseln.

Angenommen, wir möchten Daten über einen bestimmten Mitarbeiter abrufen, wenn wir auf seinen Namen klicken. Wir können den useHistory Hook verwenden, um zu der neuen Seite zu navigieren, auf der die Informationen des Mitarbeiters angezeigt werden.

 function moveToPage = (id) =>{ history.push(`/employees/${id}`) }

Wir können dies in unserer Employee.js -Datei implementieren, indem wir Folgendes hinzufügen.

 import { useEffect } from "react"; import { Link, useHistory, useLocation } from "react-router-dom"; export default function Employees() { const history = useHistory(); function pushToPage = (id) => { history.push(`/employees/${id}`) } ... return ( <div> ... <h1>List of Employees</h1> {employees.map((employee) => ( <div key={employee.id}> <span>{`${employee.firstName} ${employee.lastName} `}</span> <button onClick={pushToPage(employee.id)}> » </button> </div> ))} </div> ); }

In der Funktion pushToPage haben wir den history des useHistory verwendet, um zur Seite des Mitarbeiters zu navigieren und die Mitarbeiter-ID daneben zu übergeben.

Der useLocation Hook

Dieser Hook wird auch mit React Router DOM geliefert. Es ist ein sehr beliebter Hook, der verwendet wird, um mit dem Abfragezeichenfolgenparameter zu arbeiten. Dieser Hook ähnelt der window.location im Browser.

 import {useLocation} from 'react' const LocationExample = () =>{ const location = useLocation() return ( ... ) } export default LocationExample

Der Hook useLocation gibt den pathname , den search , den hash und den state zurück. Zu den am häufigsten verwendeten Parametern gehören der pathname und die search , aber Sie können auch hash verwenden und in Ihrer Anwendung viel state .

Die Eigenschaft location pathname gibt den Pfad zurück, den wir in unserer Route festgelegt haben. Während die search den Suchparameter der Abfrage zurückgibt, falls vorhanden. Wenn wir beispielsweise 'http://mywebsite.com/employee/?id=1' an unsere Abfrage übergeben, wäre der pathname /employee und die search wäre ?id=1 .

Wir können dann die verschiedenen Suchparameter mithilfe von Paketen wie Query-String oder durch Codierung abrufen.

Der useParams Hook

Wenn wir unsere Route mit einem URL-Parameter in ihrem path-Attribut einrichten, können wir diese Parameter als Schlüssel/Wert-Paare mit dem useParams Hook auswerten.

Nehmen wir zum Beispiel an, dass wir die folgende Route haben.

 <Route path='/employees/:id' > <Employees /> </Route>

Die Route erwartet eine dynamische ID anstelle von :id .

Mit dem useParams Hook können wir die vom Benutzer übergebene ID auswerten, falls vorhanden.

Angenommen, der Benutzer übergibt beispielsweise Folgendes in Funktion mit history.push :

 function goToPage = () => { history.push(`/employee/3`) }

Wir können den useParams Hook verwenden, um auf diesen URL-Parameter wie folgt zuzugreifen.

 import {useParams} from 'react-router-dom' const ParamsExample = () =>{ const params = useParams() console.log(params) return( <div> ... </div> ) } export default ParamsExample

Wenn wir params in der Konsole protokollieren, erhalten wir das folgende Objekt {id: "3"} .

Der useRouteMatch Hook

Dieser Hook bietet Zugriff auf das Match-Objekt. Es gibt die beste Übereinstimmung mit einer Komponente zurück, wenn ihr kein Argument übergeben wird.

Das Match-Objekt gibt mehrere Parameter zurück, darunter den path (derselbe wie der in Route angegebene Pfad), die URL , das params Objekt und isExact .

Beispielsweise können wir useRouteMatch verwenden, um Komponenten basierend auf der Route zurückzugeben.

 import { useRouteMatch } from "react-router-dom"; import Employees from "..."; import Admin from "..." const CustomRoute = () => { const match = useRouteMatch("/employees/:id"); return match ? ( <Employee /> ) : ( <Admin /> ); }; export default CustomRoute;

Im obigen Code haben wir den Pfad einer Route mit useRouteMatch und dann die Komponente <Employee /> oder <Admin /> gerendert, je nach der vom Benutzer ausgewählten Route.

Damit dies funktioniert, müssen wir die Route noch zu unserer App.js -Datei hinzufügen.

 ... <Route> <CustomRoute /> </Route> ...

Erstellen eines benutzerdefinierten Hooks

Laut der React-Dokumentation ermöglicht uns das Erstellen eines benutzerdefinierten Hooks, eine Logik in eine wiederverwendbare Funktion zu extrahieren. Sie müssen jedoch sicherstellen, dass alle Regeln, die für React-Hooks gelten, auch für Ihren benutzerdefinierten Hook gelten. Überprüfen Sie die Regeln des React-Hooks oben in diesem Tutorial und stellen Sie sicher, dass Ihr benutzerdefinierter Hook mit jedem von ihnen übereinstimmt.

Benutzerdefinierte Hooks ermöglichen es uns, Funktionen einmal zu schreiben und sie bei Bedarf wiederzuverwenden und somit dem DRY-Prinzip zu gehorchen.

Zum Beispiel könnten wir einen benutzerdefinierten Hook erstellen, um die Bildlaufposition auf unserer Seite wie folgt zu erhalten.

 import { useLayoutEffect, useState } from "react"; export const useScrollPos = () => { const [scrollPos, setScrollPos] = useState({ x: 0, y: 0 }); useLayoutEffect(() => { const getScrollPos = () => setScrollPos({ x: window.pageXOffset, y: window.pageYOffset }); window.addEventListener("scroll", getScrollPos); return () => window.removeEventListener("scroll", getScrollPos); }, []); return scrollPos; };

Hier haben wir einen benutzerdefinierten Hook definiert, um die Bildlaufposition auf einer Seite zu bestimmen. Um dies zu erreichen, haben wir zuerst einen Zustand, scrollPos , erstellt, um die Bildlaufposition zu speichern. Da dies das DOM ändern wird, müssen wir useLayoutEffect anstelle von useEffect . Wir haben einen Scroll-Ereignis-Listener hinzugefügt, um die x- und y-Scroll-Positionen zu erfassen, und dann den Ereignis-Listener bereinigt. Schließlich kehrten wir zur Scroll-Position zurück.

Wir können diesen benutzerdefinierten Hook überall in unserer Anwendung verwenden, indem wir ihn aufrufen und genauso verwenden, wie wir jeden anderen Zustand verwenden würden.

 import {useScrollPos} from './Scroll' const App = () =>{ const scrollPos = useScrollPos() console.log(scrollPos.x, scrollPos.y) return ( ... ) } export default App

Hier haben wir den benutzerdefinierten Hook useScrollPos importiert, den wir oben erstellt haben. Dann haben wir es initialisiert und dann den Wert in unserer Konsole protokolliert. Wenn wir auf der Seite scrollen, zeigt uns der Haken die Scrollposition bei jedem Schritt des Scrollens.

Wir können benutzerdefinierte Hooks erstellen, um so ziemlich alles zu tun, was wir uns in unserer App vorstellen können. Wie Sie sehen können, müssen wir einfach den eingebauten React-Hook verwenden, um einige Funktionen auszuführen. Wir können auch Bibliotheken von Drittanbietern verwenden, um benutzerdefinierte Hooks zu erstellen, aber wenn wir dies tun, müssen wir diese Bibliothek installieren, um den Hook verwenden zu können.

Fazit

In diesem Tutorial haben wir uns einige nützliche React-Hooks angesehen, die Sie in den meisten Ihrer Anwendungen verwenden werden. Wir haben untersucht, was sie darstellen und wie Sie sie in Ihrer Anwendung verwenden können. Wir haben uns auch mehrere Codebeispiele angesehen, um Ihnen zu helfen, diese Hooks zu verstehen und sie auf Ihre Anwendung anzuwenden.

Ich ermutige Sie, diese Hooks in Ihrer eigenen Anwendung auszuprobieren, um sie besser zu verstehen.

Ressourcen aus The React Docs

  • Hooks-FAQ
  • Redux-Toolkit
  • Verwenden des State-Hooks
  • Verwenden des Effekthakens
  • Hooks-API-Referenz
  • Redux-Hooks reagieren
  • Router-Hooks reagieren