Научете React Context за 5 минути - Урок за начинаещи

API на Context на React се превърна в държавен инструмент за избор на мнозина, често замествайки Redux изобщо. В този бърз 5-минутен урок ще видите въведение в това какво е контекстът и как да го използвате!

Ако искате подходящо въведение в тази тема, можете да се присъедините към списъка с чакащи за предстоящия ми усъвършенстван курс React или ако все още сте начинаещ, разгледайте безплатния ми уводен курс за React.

Помислете за това дърво, в което долните полета представляват отделни компоненти:

Дърво на компонентите

Можем лесно да добавяме състояние към долните компоненти, но досега единственият начин за предаване на данни на брат или сестра на компонент беше да се премести състояние към по-висок компонент и след това да се предаде обратно на брат или сестра чрез подпори.

Предаване на данни чрез реквизит

Ако по-късно разберем, че братът и сестрата на компонента със състояние също се нуждаят от данните, трябва отново да вдигнем състоянието и да го предадем обратно надолу:

Преминаване на състояние надолу през множество нива

Докато това решение работи, проблемите започват, ако компонент от различен клон се нуждае от данни:

По-отдалеченият компонент изисква данни

В този случай трябва да предадем състояние от най-горното ниво на приложението през всички междинни компоненти до този, който се нуждае от данните в долната част, въпреки че нивата на посредниците не се нуждаят от него. Този досаден и отнемащ време процес е известен като пробиване на опора .

Пробивно пробиване

Тук влиза Context API. Той осигурява начин за предаване на данни през дървото на компонентите чрез двойка доставчик-потребител, без да се налага да предавате подпори през всяко ниво. Мислете за това като за компоненти, които играят Catch с данни - посредническите компоненти може дори да не „знаят“, че нещо се случва:

Контекст в действие

За да демонстрираме това, ще създадем това фънки (и супер полезно) превключващо изображение от ден на нощ.

Ако искате да видите пълния код, не забравяйте да разгледате площадката на Scrimba за тази статия.

Създаване на контекст

За начало създаваме нов контекст. Тъй като искаме цялото приложение да има достъп до това, ние отиваме 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") ); 

Консумиране на контекст с contextType

В момента в App.js, ние просто връщаме компонента.

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

Нашата цел е да използваме Context, за да превключим classNames Image.jsот Dayв Night, в зависимост от това кое изображение искаме да изобразим. За да направите това, ние добавяме статично свойство към нашия извикан компонент ContextTypeи след това използваме интерполация на низове, за да го добавим към classNames в компонента.

Сега classNames съдържа низ от 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; 

Контекст. Потребител

За съжаление този подход работи само с базирани на класа компоненти. Ако вече сте научили за Hooks in React, ще знаете, че днес можем да правим почти всичко с функционални компоненти. Така че за добра мярка трябва да преобразуваме нашите компоненти във функционални компоненти и след това да използваме ThemeContext.Consumerкомпонент за предаване на информация през приложението.

Това се прави чрез обвиване на елементите ни в екземпляр от и в него (където е childrenдвижението), като се предоставя функция, която връща елементите. Това използва модела "render prop", където ние осигуряваме редовна функция като дете, което връща някои JSX за рендиране.

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 }; 

Забележка: свойството стойност сега се обработва в новия файл ThemeContext.js и следователно трябва да бъде премахнато от index.js.

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

За да свържем бутона, първо добавяме състояние към 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}; } } 

След това преминаваме valueкъм обект, съдържащ {theme: this.state.theme, toggleTheme: this.toggleTheme}, и актуализираме всички места, където използваме една стойност, за да търсим themeв обект. Това означава, че всеки themeстава contextи всяко позоваване на themeкаква стойност става context.theme.

И накрая, казваме на бутона да изслуша onClickсъбитието и след това да се задейства context.toggleTheme- това актуализира потребителите, които използват състоянието от доставчика. Кодът за бутона изглежда така:

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

Нашият бутон вече превключва изображението между нощ и ден с едно кликване!

Контекстни предупреждения

Както всички добри неща в кода, има някои предупреждения за използване на контекст:

  • 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

Този пример е доста прост и вероятно би било по-лесно да поставите състояние в приложението и да го предадете чрез подпори. Надяваме се обаче да покаже силата на потребителите, които имат достъп до данните независимо от компонентите над тях в дървото.

За да научите повече за React Context и други страхотни функции на React, можете да се присъедините към списъка с чакащи за предстоящия ми усъвършенстван курс React. Или ако търсите по-приятелски настроени за начинаещи, можете да разгледате моя безплатен уводен курс за React.

Приятно кодиране :)