Pierwsze kroki z interfejsem React Hooks API
Opublikowany: 2022-03-10Kiedy React 16.8 został oficjalnie wydany na początku lutego 2019 r., był dostarczany z dodatkowym API, które pozwala używać stanu i innych funkcji w React bez pisania klasy. Ten dodatkowy interfejs API nazywa się hookami i staje się popularny w ekosystemie React, od projektów o otwartym kodzie źródłowym po wykorzystanie w aplikacjach produkcyjnych.
Hooki w React są całkowicie opt-in, co oznacza, że przepisywanie istniejącego kodu jest niepotrzebne, nie zawierają żadnych istotnych zmian i są dostępne do użycia wraz z wydaniem React 16.8. Niektórzy ciekawscy programiści korzystali z API Hooks jeszcze przed jego oficjalnym wydaniem, ale wtedy nie było ono stabilne i było tylko funkcją eksperymentalną. Teraz jest stabilny i zalecany dla programistów React.
Uwaga : nie będziemy mówić ogólnie o React lub JavaScript. Dobra znajomość ReactJS i JavaScript przyda się podczas pracy z tym samouczkiem.
Czym są haki reagujące?
React Hooki to wbudowane funkcje, które pozwalają programistom Reacta na używanie metod stanu i cyklu życia wewnątrz komponentów funkcjonalnych, a także współpracują z istniejącym kodem, dzięki czemu można je łatwo zaadaptować do bazy kodu. Sposób, w jaki hooki zostały zaprezentowane opinii publicznej, polegał na tym, że pozwalały programistom używać stanu w komponentach funkcjonalnych, ale pod maską hooki są znacznie potężniejsze. Pozwalają programistom React cieszyć się następującymi korzyściami:
- Ulepszone ponowne wykorzystanie kodu;
- Lepsza kompozycja kodu;
- Lepsze wartości domyślne;
- Udostępnianie logiki niewizualnej za pomocą niestandardowych hooków;
- Elastyczność poruszania się w górę iw dół drzewa
components
.
Dzięki React Hooks programiści uzyskują możliwość używania komponentów funkcjonalnych do prawie wszystkiego, co muszą zrobić, od renderowania interfejsu użytkownika po obsługę stanu i logiki — co jest całkiem zgrabne.
Motywacja stojąca za wydaniem React Hooks
Zgodnie z oficjalną dokumentacją ReactJS, powody wydania React Hooks są następujące:
- Ponowne użycie logiki stanowej między komponentami jest trudne.
Dzięki hookom możesz ponownie używać logiki między komponentami bez zmiany ich architektury lub struktury. - Złożone komponenty mogą być trudne do zrozumienia.
Kiedy komponenty stają się większe i wykonują wiele operacji, na dłuższą metę trudno to zrozumieć. Hooki rozwiązują ten problem, umożliwiając rozdzielanie konkretnego pojedynczego komponentu na różne mniejsze funkcje na podstawie tego, jakie części tego oddzielonego komponentu są powiązane (takich jak konfigurowanie subskrypcji lub pobieranie danych), zamiast wymuszania podziału na podstawie metod cyklu życia. - Zajęcia są dość zagmatwane.
Zajęcia są przeszkodą w prawidłowej nauce Reagowania; musisz zrozumieć, jakthis
działa w JavaScript, który różni się od innych języków. React Hooks rozwiązuje ten problem, umożliwiając programistom korzystanie z najlepszych funkcji Reacta bez konieczności używania klas.
Zasady haków
Istnieją dwie główne zasady, których należy ściśle przestrzegać, zgodnie z zaleceniami głównego zespołu React, które zostały przedstawione w dokumentacji propozycji haków.
- Upewnij się, że hooki nie są używane w pętlach, warunkach lub funkcjach zagnieżdżonych;
- Używaj hooków tylko z wnętrza React Functions.
Podstawowe haki reakcji
Jest 10 wbudowanych haczyków, które zostały dostarczone z React 16.8, ale podstawowe (powszechnie używane) haki obejmują:
-
useState()
-
useEffect()
-
useContext()
-
useReducer()
Są to 4 podstawowe hooki, które są powszechnie używane przez programistów React, którzy zaadoptowali je w swoich bazach kodu.
useState()
useState()
pozwala programistom Reacta aktualizować, obsługiwać i manipulować stanem wewnątrz komponentów funkcjonalnych bez konieczności konwertowania go na komponent klasy. Użyjmy poniższego fragmentu kodu, który jest prostym komponentem licznika wieku i użyjemy go do wyjaśnienia mocy i składni useState()
.
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> }
Jeśli zauważyłeś, nasz komponent wygląda dość prosto, zwięźle i jest teraz komponentem funkcjonalnym, a także nie ma poziomu złożoności, jaki miałby komponent klasy.
useState()
otrzymuje stan początkowy jako argument, a następnie zwraca, korzystając z destrukturyzacji tablicy w JavaScript, dwie zmienne w tablicy można nazwać what. Pierwsza zmienna to aktualny stan, natomiast druga zmienna to funkcja, która służy do aktualizacji stanu poprzez podanie nowego stanu.

Tak powinien wyglądać nasz komponent, gdy jest renderowany w naszej aplikacji React. Klikając przycisk „Zwiększ mój wiek”, stan wieku zmieni się, a składnik będzie działał tak samo, jak składnik klasy ze stanem.
useEffect()
useEffect()
akceptuje funkcję, która zawierałaby efektywny kod. W komponentach funkcjonalnych efekty takie jak mutacje, subskrypcje, liczniki czasu, logowanie i inne efekty nie mogą być umieszczane wewnątrz komponentu funkcjonalnego, ponieważ prowadziłoby to do wielu niespójności podczas renderowania interfejsu użytkownika, a także do mylących błędów.
Korzystając z useEffect()
, przekazana do niego efektywna funkcja zostanie wykonana zaraz po wyświetleniu renderowania na ekranie. Efekty są w zasadzie zerkane na imperatywny sposób budowania interfejsów użytkownika, który jest zupełnie inny niż funkcjonalny sposób Reacta.
Domyślnie efekty są wykonywane głównie po zakończeniu renderowania, ale możesz je również uruchomić, gdy zmienią się pewne wartości.
Funkcja useEffect()
wykorzystuje głównie efekty uboczne, które są zwykle używane do interakcji z interfejsem API przeglądarki/DOM lub zewnętrznym interfejsem API, takim jak pobieranie danych lub subskrypcje. Ponadto, jeśli już wiesz, jak działają metody cyklu życia Reacta, możesz pomyśleć o useEffect()
jako o montowaniu , aktualizowaniu i odmontowywaniu komponentów — wszystko połączone w jednej funkcji. Pozwala nam replikować metody cyklu życia w komponentach funkcjonalnych.
Użyjemy poniższych fragmentów kodu, aby wyjaśnić najbardziej podstawowy sposób, w jaki możemy użyć haka useEffect()
.
Krok 1: Zdefiniuj stan swojej aplikacji
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
Tak jak omówiliśmy w poprzedniej sekcji, jak używać useState()
do obsługi stanu wewnątrz komponentów funkcjonalnych, użyliśmy go w naszym fragmencie kodu, aby ustawić stan dla naszej aplikacji, która renderuje moje imię i nazwisko.
Krok 2: Wywołaj hook useEffect
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
Zaimportowaliśmy teraz hak useEffect
, a także wykorzystaliśmy funkcję useEffect()
, aby ustawić stan właściwości name and surname, co jest całkiem zgrabne i zwięzłe.
Być może zauważyłeś przechwycenie useEffect
w drugim argumencie, który jest pustą tablicą; dzieje się tak, ponieważ zawiera wywołanie setFullName
, które nie ma listy zależności. Przekazanie drugiego argumentu zapobiegnie nieskończonemu łańcuchowi aktualizacji ( componentDidUpdate()
), a także pozwoli naszemu useEffect()
działać jako metoda cyklu życia componentDidMount
i renderować raz bez ponownego renderowania przy każdej zmianie w drzewie.
Nasza aplikacja React powinna teraz wyglądać tak:

useEffect
(duży podgląd) Możemy również użyć właściwości change title
naszej aplikacji wewnątrz funkcji useEffect()
, wywołując funkcję setTitle()
, na przykład:

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
Teraz po zrenderowaniu naszej aplikacji wyświetla się nowy tytuł.

useContext()
useContext()
akceptuje obiekt kontekstu, tj. wartość zwracaną z React.createContext
, a następnie zwraca bieżącą wartość kontekstu dla tego kontekstu.
Ten haczyk zapewnia funkcjonalnym komponentom łatwy dostęp do kontekstu aplikacji React. Przed wprowadzeniem haka useContext
musiałbyś ustawić contextType
lub <Consumer>
, aby uzyskać dostęp do swojego globalnego stanu przekazanego przez jakiegoś dostawcę w komponencie klasy.
Zasadniczo hak useContext
współpracuje z interfejsem API React Context, który umożliwia głębokie udostępnianie danych w całej aplikacji bez konieczności ręcznego przekazywania właściwości aplikacji na różnych poziomach. Teraz useContext()
nieco ułatwia korzystanie z Context.
Poniższe fragmenty kodu pokażą, jak działa Context API i jak useContext
Hook to ulepsza.
Normalny sposób korzystania z API kontekstowego
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"));
Przeanalizujmy teraz fragment kodu i wyjaśnijmy każdą koncepcję.
Poniżej tworzymy kontekst o nazwie NumberContext
. Ma to na celu zwrócenie obiektu o dwóch wartościach: { Provider, Consumer }
.
const NumberContext = React.createContext();
Następnie używamy wartości Provider
, która została zwrócona z utworzonego przez nas NumberContext
, aby udostępnić określoną wartość wszystkim dzieciom.
function App() { return ( <NumberContext.Provider value={45}> <div> <Display /> </div> </NumberContext.Provider> ); }
Dzięki temu możemy użyć wartości Consumer
, która została zwrócona z utworzonego przez nas NumberContext
, aby uzyskać wartość, którą udostępniliśmy wszystkim dzieciom. Jeśli zauważyłeś, ten komponent nie otrzymał żadnych rekwizytów.
function Display() { return ( <NumberContext.Consumer> {value => <div>The answer to the question is {value}.</div>} </NumberContext.Consumer> ); } ReactDOM.render(<App />, document.querySelector("#root"));
Zwróć uwagę, jak udało nam się uzyskać wartość ze składnika App
do składnika Display
, zawijając naszą zawartość w NumberContext.Consumer
i używając metody render props w celu pobrania wartości i jej renderowania.
Wszystko działa dobrze, a metoda render props, której użyliśmy, jest naprawdę dobrym wzorcem do obsługi danych dynamicznych, ale na dłuższą metę wprowadza niepotrzebne zagnieżdżanie i zamieszanie, jeśli nie jesteś do tego przyzwyczajony.
Korzystanie z metody useContext
Aby wyjaśnić metodę useContext
, przepiszemy komponent Display
, używając zaczepu useContext.
// 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>; }
To wszystko, co musimy zrobić, aby pokazać naszą wartość. Całkiem schludny, prawda? Wywołujesz hook useContext()
i przekazujesz go w utworzonym przez nas obiekcie context, a my pobieramy z niego wartość.
Uwaga: Nie zapominaj, że argumentem przekazywanym do hooka useContext musi być sam obiekt context, a każdy komponent wywołujący useContext będzie zawsze ponownie renderowany po zmianie wartości kontekstu.
useReducer()
Hak useReducer
służy do obsługi złożonych stanów i przejść w stanach. Przyjmuje funkcję reducer
, a także wejście stanu początkowego; następnie zwraca aktualny stan, a także funkcję dispatch
jako dane wyjściowe za pomocą destrukturyzacji tablicy.
Poniższy kod to poprawna składnia dla użycia useReducer
.
const [state, dispatch] = useReducer(reducer, initialArg, init);
Jest to swego rodzaju alternatywa dla useState
; zazwyczaj preferowane jest useState
, gdy masz złożoną logikę stanów, która ma do czynienia z wieloma podwartościami lub gdy następny stan jest zależny od poprzedniego.
Dostępne inne haki React
useCallback | To przechwycenie zwraca funkcję zwrotną, która jest zapamiętana i która zmienia się tylko wtedy, gdy zmieni się jedna zależność w drzewie zależności. |
useMemo | Ten hook zwraca zapamiętaną wartość, którą możesz przekazać w funkcji „utwórz”, a także tablicę zależności. Zwracana wartość użyje zapamiętanej wartości ponownie tylko wtedy, gdy zmieni się jedna z zależności w drzewie zależności. |
useRef | Ten zaczep zwraca modyfikowalny obiekt ref, którego właściwość .current jest inicjowana do przekazanego argumentu ( initialValue ). Zwrócony obiekt będzie dostępny przez cały okres istnienia komponentu. |
useImperativeHandle | Ten zaczep służy do dostosowywania wartości instancji, która jest udostępniana dla komponentów nadrzędnych podczas korzystania z referencji w React. |
useLayoutEffect | Ten haczyk jest podobny do haczyka useEffect , jednak uruchamia się synchronicznie po wszystkich mutacjach DOM. Jest również renderowany w taki sam sposób, jak componentDidUpdate i componentDidMount . |
useDebugValue | Ten haczyk może być używany do wyświetlania etykiet niestandardowych haków w narzędziach React Dev. Jest to bardzo przydatne do debugowania za pomocą narzędzi React Dev Tools. |
Niestandardowe haki reakcji
„Niestandardowy hook” to funkcja JavaScript, której nazwy są poprzedzone słowem use
i mogą być używane do wywoływania innych hooków. Pozwala także wyodrębnić logikę komponentów do funkcji wielokrotnego użytku; są to normalne funkcje JavaScript, które mogą korzystać z innych hooków w swoim wnętrzu, a także zawierają wspólną logikę stanową, z której można korzystać w wielu komponentach.
Poniższe fragmenty kodu przedstawiają przykład niestandardowego haka React do implementacji nieskończonego przewijania (autorstwa 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; };
Ten niestandardowy hook akceptuje dwa argumenty, którymi są start
i pace
. Argument start to początkowa liczba elementów, które mają być renderowane, a argument pace to kolejna liczba elementów, które mają być renderowane. Domyślnie argumenty start
i pace
są ustawione odpowiednio na 30
i 10
, co oznacza, że faktycznie możesz wywołać Hook bez żadnych argumentów i zamiast tego zostaną użyte te wartości domyślne.
Aby więc użyć tego hooka w aplikacji React, użyjemy go z internetowym API, które zwraca „fałszywe” dane:
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;
Powyższy kod wyrenderuje listę fałszywych danych ( userID
i title
), które wykorzystują nieskończony hak przewijania do wyświetlania początkowej liczby danych na ekranie.
Wniosek
Mam nadzieję, że praca z tym samouczkiem Ci się podobała. Zawsze możesz przeczytać więcej o React Hooks z poniższych odnośników.
Jeśli masz jakieś pytania, możesz je zostawić w sekcji komentarzy, a ja z przyjemnością odpowiem na każde!
Repozytorium wspierające ten artykuł jest dostępne na Github.
Zasoby i dalsze czytanie
- „Odniesienie do interfejsu Hooks API”, React.js Docs
- „Czym są React Hooki?”, Robin Wieruch
- „Jak działa hook
useContext
”, Dave Ceddia - „React Hooks: jak używać
useEffect()
”, Hossein Ahmadi, Medium - „Pisanie własnych niestandardowych haków reakcyjnych”, Aayush Jaiswal, Medium
- „Łatwe do zrozumienia przepisy React Hook”, Gabe Ragland, useHooks()