Научите контекст реакције за 5 минута - Водич за почетнике

Реацт-ов Цонтект АПИ за многе је постао изабрано средство управљања државом, често замењујући Редук. У овом брзом петоминутном упутству видећете увод у то шта је контекст и како га користити!

Ако желите прави увод у ову тему, можете се придружити листи чекања за мој предстојећи напредни курс Реацт, или ако сте још увек почетник, погледајте мој бесплатни уводни курс о Реацту.

Узмите у обзир ово стабло у коме доњи оквири представљају одвојене компоненте:

Стабло компонената

Лако можемо додати стање доњим компонентама, али до сада је једини начин за прослеђивање података брату или сестри компоненте био премештање стања у вишу компоненту, а затим враћање натраг брату или сестри путем пропе.

Прослеђивање података путем реквизита

Ако касније откријемо да су брату и сестри компоненте са стањем такође потребни подаци, морамо поново да подигнемо стање и проследимо га назад:

Преношење стања кроз више нивоа

Иако ово решење функционише, проблеми почињу ако компоненти на другој грани требају подаци:

Удаљенија компонента захтева податке

У овом случају, морамо да пренесемо стање са горњег нивоа апликације кроз све посредничке компоненте на ону којој су потребни подаци на дну, иако посредничким нивоима то није потребно. Овај досадан и дуготрајан поступак познат је под називом бушење подупирача .

Бушење подупирача

Овде долази Цонтект АПИ. Он пружа начин преношења података кроз стабло компонената преко пара добављача и потрошача, без потребе за пропуштањем реквизита кроз сваки ниво. Замислите то као компоненте које играју Цатцх с подацима - посредничке компоненте можда чак и не „знају“ да се било шта догађа:

Контекст на делу

Да бисмо то демонстрирали, створићемо ову фанки (и супер корисну) слику пребацивања из дана у ноћ.

Ако желите да видите пуни код, обавезно погледајте игралиште Сцримба за овај чланак.

Стварање контекста

За почетак креирамо нови контекст. Како желимо да цела апликација има приступ овоме, идемо index.jsи умотавамо је у апликацију ThemeContext.Provider.

Такође преносимо valueреквизит нашем добављачу. Овде се чувају подаци које желимо да сачувамо. За сада само убацујемо 'Day'.

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

Конзумирање контекста са цонтектТипе

Тренутно, у App.js, једноставно враћамо компоненту.

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

Наш циљ је да помоћу контекста пребацимо цлассНамес Image.jsиз Dayу Night, у зависности од тога коју слику желимо да прикажемо. Да бисмо то урадили, нашој позваној компоненти додајемо статичко својство, ContextTypeа затим користимо интерполацију низа да бисмо је додали у цлассНамес у компоненти.

Сада цлассНамес садрже низ из valueреквизита. Напомена: Преселио сам се ThemeContextу сопствену датотеку да бих спречио грешку.

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; 

Цонтект.Цонсумер

Нажалост, овај приступ функционише само са компонентама заснованим на класама. Ако сте већ сазнали за Хоокс ин Реацт, знаћете да данас можемо учинити готово све са функционалним компонентама. Дакле, за добру меру, требали бисмо претворити наше компоненте у функционалне компоненте, а затим их користити ThemeContext.Consumerза проношење информација кроз апликацију.

То се постиже умотавањем наших елемената у инстанцу и унутар ње (тамо где childrenиде), пружајући функцију која враћа елементе. Ово користи образац „рендер проп“ где пружамо редовну функцију као дете које враћа неки ЈСКС у приказ.

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; 

Напомена: Такође морамо умотати компоненту - то нам омогућава да касније додамо функционалност дугмета.

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

Издвоји добављач контекста

Тренутно преносимо чврсто кодирану вредност преко добављача, међутим, наш циљ је да дугметом пребацимо између ноћи и дана.

Ово захтева премештање нашег добављача у засебну датотеку и стављање у сопствену компоненту, у овом случају названу 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 }; 

Напомена: својством вредности се сада рукује у новој датотеци ТхемеЦонтект.јс и стога га треба уклонити из индек.јс.

Промена контекста

Да бисмо повезали дугме, прво додамо стање у 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 }; 

Затим додајемо методу за пребацивање између дана и ноћи:

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

Сада променимо valueсвојство у this.state.themeтако да враћа податке из стања.

 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

Овај пример је прилично једноставан и вероватно би било лакше ставити стање у апликацију и пренети га путем реквизита. Међутим, надамо се да показује моћ постојања потрошача који могу приступити подацима независно од компонената изнад њих у стаблу.

Да бисте сазнали више о Реацт Цонтект-у и другим сјајним карактеристикама Реацт-а, можете се придружити листи чекања за мој предстојећи напредни Реацт курс. Или ако тражите више почетнике, можете погледати мој бесплатни уводни курс о Реацт-у.

Срећно кодирање :)