Lær reager kontekst på 5 minutter - en begyndervejledning

React's Context API er blevet det valgte statsstyringsværktøj for mange og erstatter ofte Redux helt. I denne hurtige 5-minutters tutorial ser du en introduktion til, hvad Context er, og hvordan du bruger det!

Hvis du vil have en ordentlig introduktion til dette emne, kan du tilmelde dig ventelisten til mit kommende avancerede React-kursus, eller hvis du stadig er nybegynder, kan du tjekke mit gratis introduktionskursus om React.

Overvej dette træ, hvor de nederste felter repræsenterer separate komponenter:

Komponent træ

Vi kan let tilføje tilstand til bundkomponenterne, men indtil nu var den eneste måde at overføre data til en komponents søskende på at flytte tilstand til en højere komponent og derefter sende den tilbage til søskende via rekvisitter.

Videregivelse af data via rekvisitter

Hvis vi senere finder ud af, at søskende til komponenten med tilstand også har brug for dataene, er vi nødt til at løfte tilstanden op igen og sende den ned igen:

At passere tilstand ned gennem flere niveauer

Mens denne løsning fungerer, begynder problemer, hvis en komponent i en anden gren har brug for dataene:

En fjernere komponent kræver data

I dette tilfælde skal vi passere tilstand fra applikationens øverste niveau gennem alle de mellemliggende komponenter til den, der har brug for dataene i bunden, selvom de mellemliggende niveauer ikke har brug for det. Denne kedelige og tidskrævende proces er kendt som propboring .

Propboring

Det er her Context API kommer ind. Det giver en måde at føre data gennem komponenttræet via et Provider-Consumer-par uden at skulle sende rekvisitter ned gennem hvert niveau. Tænk på det som de komponenter, der spiller Fang med data - de mellemliggende komponenter "ved" ikke engang, at der sker noget:

Kontekst i aktion

For at demonstrere dette opretter vi dette funky (og super nyttigt) skiftbillede fra dag til nat.

Hvis du vil se den fulde kode, skal du sørge for at tjekke Scrimba-legepladsen til denne artikel.

Opret kontekst

Til at begynde med opretter vi en ny kontekst. Da vi ønsker, at hele appen skal have adgang til dette, går vi til index.jsog pakker appen ind ThemeContext.Provider.

Vi sender også valuerekvisitten til vores udbyder. Dette indeholder de data, vi vil gemme. For nu hardcoder vi bare ind 'Day'.

import React from "react"; import ReactDOM from "react-dom"; import ThemeContext from "./themeContext"; import App from "./App"; ReactDOM.render(   , document.getElementById("root") ); 

Forbruger sammenhæng med contextType

I øjeblikket App.jsreturnerer vi simpelthen komponenten.

import React from "react"; import Image from "./Image"; class App extends React.Component { render() { return ( ); } } export default App; 

Vores mål er at bruge Context til at skifte classNames ind Image.jsfra Daytil Night, afhængigt af hvilket billede vi vil gengive. For at gøre dette tilføjer vi en statisk egenskab til vores kaldte komponent ContextTypeog bruger derefter strenginterpolering til at føje den til classNames i komponenten.

Nu indeholder classNames strengen fra valueprop. Bemærk: Jeg er flyttet ThemeContexttil sin egen fil for at forhindre en fejl.

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; class Image extends React.Component { render() { const theme = this.context; return ( ); } } Image.contextType = ThemeContext; export default Image; 

Kontekst. Forbruger

Desværre fungerer denne tilgang kun med klassebaserede komponenter. Hvis du allerede har lært om Hooks in React, ved du, at vi kan gøre næsten hvad som helst med funktionelle komponenter i disse dage. Så for godt mål skal vi konvertere vores komponenter til funktionelle komponenter og derefter bruge ThemeContext.Consumerkomponenten til at videregive info gennem appen.

Dette gøres ved at indpakke vores elementer i en forekomst af og inden for det (hvor du er på childrenfarten), hvilket giver en funktion, der returnerer elementerne. Dette bruger "render prop" -mønsteret, hvor vi leverer en regelmæssig funktion som barn, der returnerer noget JSX til gengivelse.

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; function Image(props) { // We don't need this anymore // const theme = this.context return (  {theme => ( )}  ); } // We don't need this anymore // Image.contextType = ThemeContext; export default Image; 

Bemærk: Vi skal også pakke komponenten ind - dette giver os mulighed for at tilføje funktionalitet til knappen senere.

import React from "react"; import ThemeContext from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

Uddrag kontekstudbyder

Vi sender i øjeblikket en hårdkodet værdi ned gennem udbyderen, men vores mål er at skifte mellem nat og dag med vores knap.

Dette kræver, at vores udbyder flyttes til en separat fil og placerer den i sin egen komponent, i dette tilfælde kaldet ThemeContextProvider.

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); class ThemeContextProvider extends Component { render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Bemærk: egenskaben værdi behandles nu i den nye fil ThemeContext.js og skal derfor fjernes fra index.js.

Ændring af kontekst

For at binde knappen op, føjer vi først tilstand til ThemeContextProvider:

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); // Note: You could also use hooks to provide state and convert this into a functional component. class ThemeContextProvider extends Component { state = { theme: "Day" }; render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Dernæst tilføjer vi en metode til at skifte mellem dag og nat:

toggleTheme = () => { this.setState(prevState => { return { theme: prevState.theme === "Day" ? "Night" : "Day" }; }); }; 

Nu ændrer vi vores valueejendom til, this.state.themeså den returnerer info fra tilstand.

 render() { return {this.props.children}; } } 

Next, we change value to an object containing {theme: this.state.theme, toggleTheme: this.toggleTheme}, and update all the places where we use a single value to look for theme in an object. This means that every theme becomes context and every reference to theme as value becomes context.theme.

Finally, we tell the button to listen for the onClick event and then fire context.toggleTheme - this updates the Consumers which are using the state from the Provider. The code for the button looks like this:

import React from "react"; import { ThemeContextConsumer } from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

Our button now switches the image between night and day in one click!

Context caveats

Like all good things in code, there are some caveats to using Context:

  • Don't use Context to avoid drilling props down just one or two layers. Context is great for managing state which is needed by large portions of an application. However, prop drilling is faster if you are just passing info down a couple of layers.

  • Avoid using Context to save state that should be kept locally. So if you need to save a user's form inputs, for example, use local state and not Context.

  • Always wrap the Provider around the lowest possible common parent in the tree - not the app's highest-level component. No need for overkill.

  • Lastly, if you pass an object as your value prop, monitor performance and refactor as necessary. This probably won't be needed unless a drop in performance is noticeable.

Wrap up

Dette eksempel er ret simpelt, og det ville sandsynligvis være lettere at sætte tilstand i appen og videregive den via rekvisitter. Det viser dog forhåbentlig styrken ved at have forbrugere, der kan få adgang til data uafhængigt af komponenterne over dem i træet.

For at lære mere om React Context og andre fantastiske funktioner i React, kan du tilmelde dig ventelisten til mit kommende avancerede React-kursus. Eller hvis du leder efter en mere nybegyndervenlig, kan du tjekke mit gratis introduktionskursus om React.

Glad kodning :)