Õppige konteksti reageerima 5 minutiga - algajate õpetus

Reakti Context API-st on saanud paljude jaoks valitud olekuhaldusvahend, sageli asendades Reduxi üldse. Selles kiires 5-minutises õpetuses näete sissejuhatust kontekstile ja kuidas seda kasutada!

Kui soovite selle teema korralikku sissejuhatust, võite liituda minu eelseisva edasijõudnute Reacti kursuse ootelehega või kui olete alles algaja, vaadake minu tasuta Reacti sissejuhatavat kursust.

Mõelge sellele puule, kus alumised kastid tähistavad eraldi komponente:

Komponendipuu

Alamkomponentidele saame hõlpsalt oleku lisada, kuid seni oli ainus viis andmete edastamiseks komponendi õele-vennale oleku teisaldamine kõrgemasse komponenti ja seejärel rekvisiitide kaudu õele-vennale tagasi andmine.

Andmete edastamine rekvisiitide kaudu

Kui saame hiljem teada, et ka olekukomponendi õde-vend vajab andmeid, peame oleku uuesti üles tõstma ja tagasi andma:

Oleku edasiandmine läbi mitme taseme

Kuigi see lahendus töötab, tekivad probleemid, kui mõne teise haru komponent vajab andmeid:

Kaugem komponent nõuab andmeid

Sellisel juhul peame edastama oleku rakenduse ülaltasandilt läbi kõigi vahenduskomponentide sellesse, mis vajab andmeid allosas, kuigi vahendustasemed seda ei vaja. Seda tüütut ja aeganõudvat protsessi nimetatakse tugipuurimiseks .

Rekvisiidi puurimine

Siit tuleb Context API. See pakub viisi andmete edastamiseks komponentipuu kaudu teenusepakkuja-tarbija kaudu, ilma et peaksite iga taseme kaudu rekvisiite edastama. Mõelge kui komponentidele, mis mängivad Catchi andmetega - vahenduskomponendid ei pruugi isegi "teada", et midagi toimub:

Kontekst tegevuses

Selle demonstreerimiseks loome selle funky (ja ülikasuliku) päevast päeva vahetava pildi.

Kui soovite näha täielikku koodi, vaadake kindlasti selle artikli Scrimba mänguväljakut.

Konteksti loomine

Alustuseks loome uue konteksti. Kuna soovime, et kogu rakendusel oleks sellele juurdepääs, läheme index.jsrakendusse ja mähkime selle sisse ThemeContext.Provider.

Anname valuerekvisiidi ka oma pakkujale. See sisaldab andmeid, mida soovime salvestada. Praegu oleme lihtsalt sisse loginud 'Day'.

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

Konteksti tarbimine kontekstitüübiga

Praegu App.jstagastame komponendi lihtsalt tagasi .

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

Meie eesmärk on kasutada Kontekst vahetada classNames in Image.jsalates Daykuni Night, sõltuvalt sellest, milline pilt tahame muuta. Selleks lisame oma nimega komponendile staatilise atribuudi ContextTypeja kasutame seejärel stringi interpoleerimist selle lisamiseks komponendis olevasse klassiNimed .

Nüüd sisaldab classNames stringi valuerekvisiidist. MärkusThemeContext . Vea vältimiseks olen oma faili kolinud .

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. Tarbija

Kahjuks töötab selline lähenemine ainult klassipõhiste komponentidega. Kui olete juba õppinud Hooks in Reacti kohta, teate, et funktsionaalsete komponentidega saame tänapäeval teha peaaegu kõike. Seega peaksime oma komponendid muundama funktsionaalseteks komponentideks ja seejärel kasutama ThemeContext.Consumerkomponenti teabe edastamiseks rakenduse kaudu.

Seda tehakse pakkides meie elemendid sellesse eksemplari ja selle sisse (kuhu childrenminna), pakkudes funktsiooni, mis tagastab elemendid. See kasutab mustrit "renderdamise prop", kus pakume lapsena tavalist funktsiooni, mis tagastab renderdamiseks mõne JSX-i.

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; 

Märkus. Peame ka komponendi sisse mähkima - see võimaldab meil nupule hiljem funktsionaalsust lisada.

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

Ekstrakti pakkuja väljavõte

Praegu edastame pakkuja kaudu rangelt kodeeritud väärtust, kuid meie eesmärk on oma nupuga vahetada öö ja päeva vahel.

See nõuab meie teenusepakkuja teisaldamist eraldi faili ja selle oma komponendi, antud juhul nn 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 }; 

Märkus. Väärtuse omadust käsitletakse nüüd uues failis ThemeContext.js ja seetõttu tuleks see indeks.js-ist eemaldada.

Konteksti muutmine

Nupu ühendamiseks lisame kõigepealt oleku 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 }; 

Järgmisena lisame päeva ja öö vahel vahetamise meetodi:

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

Nüüd muudame oma valuevara this.state.themeselliseks, et see tagastaks teabe olekust.

 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

See näide on üsna lihtne ja ilmselt oleks lihtsam rakendusse olekut lisada ja seda rekvisiitide kaudu edasi anda. Loodetavasti näitab see aga võimalust, et tarbijatel on juurdepääs andmetele sõltumata nende puu kohal asuvatest komponentidest.

Reacti konteksti ja muude Reacti suurepäraste funktsioonide kohta lisateabe saamiseks võite liituda minu eelseisva täpsema Reacti kursuse ootelehega. Või kui otsite algajale sõbralikumat, võite vaadata minu tasuta Reacti tutvustavat kursust.

Head kodeerimist :)