Научите контекст реакције за 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
Овај пример је прилично једноставан и вероватно би било лакше ставити стање у апликацију и пренети га путем реквизита. Међутим, надамо се да показује моћ постојања потрошача који могу приступити подацима независно од компонената изнад њих у стаблу.
Да бисте сазнали више о Реацт Цонтект-у и другим сјајним карактеристикама Реацт-а, можете се придружити листи чекања за мој предстојећи напредни Реацт курс. Или ако тражите више почетнике, можете погледати мој бесплатни уводни курс о Реацт-у.
Срећно кодирање :)