React Context API: To nie takie trudne, jak myślisz

React Context dostarcza danych o komponentach niezależnie od poziomu drzewa komponentów. Kontekst umożliwia zarządzanie danymi globalnymi, takimi jak globalne usługi tematyczne, preferencje użytkownika, powiadomienia i inne.

Przewodnik po React Context i hooku useContext()

React Context dostarcza danych o komponentach niezależnie od poziomu drzewa komponentów. Kontekst umożliwia zarządzanie danymi globalnymi, takimi jak globalne usługi tematyczne, preferencje użytkownika, powiadomienia i inne.

Z drugiej strony, można mieć Konteksty dla każdej ważniejszej części aplikacji. Jeśli tworzysz aplikację eCommerce react, możesz mieć Context dla koszyka, Context dla stron konta, kasy i tak dalej.

Kontekst zapewnia dane i metody dla komponentów podrzędnych, więc koszyk potrzebuje danych o produktach w koszyku. Oferuje metody manipulowania koszykiem, takie jak dodawanie elementów, usuwanie, stosowanie kodów rabatowych itp.

Lubię Reacta, ponieważ możemy znaleźć wiele różnych rozwiązań dla różnych problemów. Mamy kilka różnych bibliotek formularzy, wiele bibliotek CSS i kilka bibliotek specjalnie ukierunkowanych na problemy z danymi stanu w React. Można się tego nauczyć poprzez doświadczenie w korzystaniu z biblioteki w swoim projekcie. Czasami możemy instalować i używać bibliotek, których nie potrzebujemy.

To samo dotyczy biblioteki zarządzania stanem. Możesz użyć zewnętrznych lub użyć Context API. Wszystko zależy od Ciebie! Warto zastanowić się trzy razy przed zainstalowaniem jakiejkolwiek biblioteki zarządzania stanem, ponieważ Context dobrze rozwiązuje problemy w typowych przypadkach.

React Context API lub zewnętrzna biblioteka zarządzania stanem

Dlaczego Context API?

React pozwala nam tworzyć aplikacje wielokrotnego użytku z komponentami, aby zmienić przeznaczenie tworzonych przez nas aplikacji. Aplikacja React zawiera więc kilka elementów. Kiedy aplikacja jest wdrażana, komponenty te są często duże i ciężkie w utrzymaniu, dlatego dzielimy je na małe części. Jest to fascynująca koncepcja w React – możesz mieć wiele komponentów i mieć wydajną i zwięzłą aplikację bez konieczności posiadania jednego, ogromnego komponentu. Podczas rozkładania mniejszych komponentów na potrzeby konserwacji mogą one potrzebować nieco więcej danych do prawidłowego działania.

Wykorzystanie wzorca Provider w Reakcie

Prawdopodobnie wiesz o prop drilling. W ramach tworzenia aplikacji prawdopodobnie będziesz próbował drążyć warstwy komponentów. Musimy wysyłać props przez różne poziomy komponentów, aby je udostępnić.

Podsumowując, prop drilling to sytuacja, w której trzeba przekazać rekwizyty do komponentu potomnego, a następnie do kolejnego komponentu potomnego i kolejnego.

Kontekst zapewnia sposób na uniknięcie wiercenia rekwizytów

Spójrz na przykład:

setUser={setUser} />; }; export const EditAccount = (props) => { const { user, setUser } = props; return ( <forma> <input type=”text” value={user.name} onChange={(e) => setUser({ …user, name: e.target.value, }) } /> <input type=”text” value={user.country} onChange={(e) => setUser({ …user, country: e.target.value, }) } /> </formularz> ); }; export const AccountDetails = props => { const { user, setUser } = props; return ( <> <h1>{user.name}</h1> <p>Kraj: {user.country}</p> <EditAccount user={user} setUser={setUser}></EditAccount> </> ); };’ style=”color:#e1e4e8;display:none” aria-label=”Copy” class=”code-block-pro-copy-button”>.
import React, { useState } from "react";

export const Account = () => {
    const [user, setUser] = useState({ name: "Marcin", country: "Poland" });

    <AccountDetails user={user} setUser={setUser} />;
};

export const EditAccount = (props) => {
    const { user, setUser } = props;

    return (
        <form>
            <input
                type="text"
                value={user.name}
                onChange={(e) =>
                    setUser({
                        ...user,
                        name: e.target.value,
                    })
                }
            />

            <input
                type="text"
                value={user.country}
                onChange={(e) =>
                    setUser({
                        ...user,
                        country: e.target.value,
                    })
                }
            />
        </form>
    );
};

export const AccountDetails = props => {
    const { user, setUser } = props;

    return (
        <>
            <h1>{user.name}</h1>
            <p>Country: {user.country}</p>

            <EditAccount user={user} setUser={setUser}></EditAccount>
        </>
    );
};

Komponent Account przekazuje props user i SetUser do komponentu AccountDetailsComponent, a AccountDetailsComponent przekazuje je do komponentu EditAccount.

Wiercenie w rekwizytach, zwane także gwintowaniem, jest dobrym i pomocnym wzorem, ale w niektórych przypadkach warto go unikać. Rozważmy sytuację, w której masz system powiadomień w swojej aplikacji. Dostępne są dwie metody:

  1. addMessage
  2. removeMessage

Chcesz mieć możliwość korzystania z tych metod w dowolnym komponencie.

Komponent nadrzędny -> komunikacja komponentów zużywających

Aby rozwiązać problemy z wierceniem podpór, obiekt globalny musi być dostępny w drzewie react bezpośrednio przez komponenty w drzewie. React Context to przydatny mechanizm, który pozwala na przekazywanie danych przez każdy komponent potomny bez konieczności wiercenia w rekwizytach. React Context może ci bardzo pomóc.

Uwaga: użycie Kontekstu w niektórych komponentach powoduje, że są one zależne od tego Kontekstu. Należy o tym pamiętać podczas projektowania aplikacji.

Tworzenie kontekstu

Aby utworzyć kontekst, należy użyć metody react createContext:

export const MessagesContext = createContext();

Dostarczanie danych do kontekstu

Każdy obiekt Context ma swój komponent Provider, który umożliwia przekazywanie danych do kontekstu.

Aby przekazać dane do komponentu Provider, należy użyć value prop:

<MyContext.Provider value={<value here>}>

Spójrzmy na prawdziwy przykład:

import React, { createContext, useReducer } from 'react';

import {

    MessagesReducer,

    messagesInitialState,

    addMessage as addMessageAction,

    removeMessage as removeMessageAction

 } from '../../reducers/Messages';

export const MessagesContext = createContext();

export const MessagesProvider = ({ children }) => {

    const [{ messages }, dispatch ] = useReducer(MessagesReducer, messagesInitialState);

    const removeMessage = message => dispatch(removeMessageAction(message));

    const addMessage = message => dispatch(addMessageAction(message));

    return <MessagesContext.Provider value={{

        messages,

        addMessage,

        removeMessage

    }}>

        {children}

    </MessagesContext.Provider>

};

Kontekst ten używa haka useReducer do zarządzania stanem i zwraca Provider z tablicą komunikatów oraz dwiema metodami: addMessage i remove message.

Wprowadzanie kontekstu do aplikacji

Aby wstrzyknąć kontekst do aplikacji, należy owinąć aplikację komponentem Provider. Zazwyczaj najlepszym miejscem do tego jest plik index.js lub app.js:

import { MessagesProvider } from './contexts/Messages';

const App = () => {
    return <MessagesProvider>
        <Router>
            <>
                <PageHeader/>
                <Messages/>
                <Switch>
                    <Route path="/category/:categoryUrlKey" component={CategoryRoute}/>
                    <Route path="/product/:productUrlKey" component={ProductRoute}/>
                </Switch>
            </>
        </Router>
    </MessagesProvider>
}

Używanie kontekstu React w komponentach z hakiem useContext

Haki React umożliwiają nam przechowywanie danych o stanie w komponentach funkcjonalnych. React ma kilka haków, które są dołączone. UseState, UseCallback, UseEffects i inne. Kolejną rzeczą, którą chcemy szczegółowo omówić, jest hak useContext. Haki UseContext umożliwiają podłączanie i korzystanie z kontekstów. Ten hook używa argumentu, który zawiera wybrany Context. Następnie można uzyskać dostęp do wartości kontekstu.

Ostatnią rzeczą, którą chcę pokazać, jest użycie Context w komponentach podrzędnych.

Wyeksportowaliśmy dwie rzeczy z pliku, w którym zadeklarowaliśmy Context:

  1. MessagesContext
  2. MessagesProvider

Użyliśmy MessagesProvider do owinięcia komponentu App. Jednocześnie MessageContext odwołuje się do naszego Kontekstu i musimy przekazać go jako argument do haka useContext w komponencie, gdy chcemy użyć tego Kontekstu.

import { MessagesContext } from '../../contexts/Messages';
const Messages = () => {

    const { messages, removeMessage, addMessage } = useContext(MessagesContext);
    (...)
};

Teraz możemy użyć wszystkich danych Context w naszym komponencie.

Podsumowanie

React Context API zapewnia inny sposób przekazywania danych do wielu komponentów, a dokładniej: do wszystkich dzieci komponentów Context. Obiekt kontekstu dostarcza dane i metody do komponentu konsumenta, a konsument odczytuje wartość kontekstu.

Alternatywnie, bez Kontekstu react, można przekazać rekwizyty ręcznie do każdego komponentu react, ale w tym przypadku napotkamy problem „props drilling”. Interfejs API kontekstu Reacta pozwala uniknąć wiercenia w rekwizytach, ale z drugiej strony – dodaje zależność między komponentami reactowymi a kontekstem.

Co więcej, testowanie komponentu react, który zużywa wartość kontekstową jest nieco bardziej skomplikowane, ale jest oczywiście podwójne i istnieje kilka wzorców, aby to zrobić. Tak czy inaczej, użycie Context jest opcją zarządzania stanem w projektach reactowych zamiast instalowania zewnętrznych bibliotek zarządzania stanem.

Kompletna konfiguracja interfejsu API kontekstu obejmuje:

  1. Tworzenie kontekstu za pomocą metody react createContext
  2. Tworzenie dostawcy kontekstu za pomocą komponentu Provider react
  3. Wstrzyknięcie dostawcy kontekstu do drzewa komponentów
  4. Wykorzystanie Contextu w następujących komponentach za pomocą haka useContext

Rzeczywisty projekt z przykładem API kontekstowego

Możesz pokazać prawdziwy przykład użycia Context w moim projekcie React-apollo-storefront tutaj.

Udostępnij post:

Możesz także polubić

Kariera w branży technologicznej: Jak rozwijać swoje umiejętności

Jesteś programistą i chciałbyś się rozwijać? W internecie znajdziesz pełno materiałów o tym, jak to zrobić. Pomimo tego nie uciekaj — mam coś, co Cię zaciekawi. Czy wiesz, że Adam Małysz — legendarny polski skoczek, zanim został mistrzem latania, to był dekarzem? Nie śmiem się porównywać z Panem Adamem, natomiast są dwie rzeczy, które nas łączą.

Ja też byłem dekarzem i też udało mi się przebranżowić. Może nie w tak spektakularny sposób, ale jednak. W tym artykule podzielę się z Tobą moim osobistym doświadczeniem, które zdobyłem na drodze od dekarza przez programistę do tech leada i dam Ci wskazówki, które będziesz mógł zastosować, aby się rozwijać i awansować, a może nawet zmienić diametralnie swoją karierę.

Czytaj więcej
AHA stack przywróćmy prostotę frontendu

AHA! Przywróćmy prostotę Frontendu

Czy zastanawiałeś się, dlaczego w dzisiejszych czasach, gdy mamy dostęp do najnowszych technologii i rozwiązań, projekty IT nadal kończą się fiaskiem? Czy nie uważasz, że w wielu przypadkach zamiast upraszczać to komplikujemy sobie życie i pracę? Czasami mniej znaczy więcej, zwłaszcza w świecie frontendu! Czytaj dalej i dowiedz się czym jest AHA stack i jak robić frontend prościej.

Czytaj więcej