Вивчіть контекст реакції за 5 хвилин - Підручник для початківців

API Context React став для багатьох інструментом управління державою, який часто замінював Redux взагалі. У цьому короткому 5-хвилинному підручнику ви побачите вступ до того, що таке контекст і як ним користуватися!

Якщо ви хочете отримати правильний вступ до цієї теми, ви можете приєднатися до списку очікування мого майбутнього вдосконаленого курсу React, або якщо ви все ще новачок, перегляньте мій безкоштовний вступний курс React.

Розглянемо це дерево, в якому внизу вікна представляють окремі компоненти:

Дерево компонентів

Ми можемо легко додати стан до нижніх компонентів, але дотепер єдиним способом передачі даних брату або сестрі компонента було переміщення стану до вищого компонента, а потім передача його назад до рідного брата через реквізит.

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

Якщо пізніше ми виявимо, що братовому брату компонента зі станом також потрібні дані, нам доведеться знову підняти стан і передати його назад:

Передача стану через кілька рівнів

Поки це рішення працює, проблеми починаються, якщо компоненту в іншій гілці потрібні дані:

Більш віддалений компонент вимагає даних

У цьому випадку нам потрібно передати стан від верхнього рівня програми через усі посередницькі компоненти до того, який потребує даних внизу, навіть якщо посередницькі рівні цього не потребують. Цей виснажливий і трудомісткий процес відомий як буріння під опорою .

Буріння опори

Тут з’являється контекстний API. Він забезпечує спосіб передачі даних через дерево компонентів через пару постачальник-споживач без необхідності передавати реквізити через кожен рівень. Думайте про це як про компоненти, що грають в Catch з даними - посередницькі компоненти можуть навіть не знати, що щось відбувається:

Контекст у дії

Щоб продемонструвати це, ми створимо цей прикольний (і надзвичайно корисний) образ перемикання щодня на ніч.

Якщо ви хочете побачити повний код, обов’язково ознайомтесь із ігровим майданчиком Скримба для цієї статті.

Створити контекст

Для початку ми створюємо новий контекст. Оскільки ми хочемо, щоб уся програма мала доступ до цього, ми переходимо до програми 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 містять рядок з valueprop. Примітка: Я перейшов 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; 

Контекст. Споживач

На жаль, такий підхід працює лише з компонентами на основі класу. Якщо ви вже дізналися про Хуки в 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 }; 

Примітка: властивість value тепер обробляється у новому файлі 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; 

Наша кнопка тепер перемикає зображення між ніччю та днем ​​одним клацанням миші!

Застереження щодо контексту

Як і всі хороші речі в коді, є деякі застереження щодо використання контексту:

  • Не використовуйте Context, щоб уникнути свердління реквізитів лише на один-два шари. Контекст чудово підходить для управління станом, який необхідний великим частинам програми. Однак буріння опори відбувається швидше, якщо ви просто передаєте інформацію на кілька шарів.

  • Уникайте використання контексту для збереження стану, який слід зберігати локально. Отже, якщо вам потрібно зберегти введення форми користувача, наприклад, використовуйте локальний стан, а не контекст.

  • Завжди обертайте Постачальника навколо найнижчого з можливих загальних батьків у дереві - а не компонента найвищого рівня програми. Не потрібно зайвого вбивства.

  • Нарешті, якщо ви передаєте об’єкт як свій значення значення, відстежуйте продуктивність та рефакторинг за необхідності. Це, мабуть, не буде потрібно, якщо не буде помітно зниження продуктивності.

Загорнути

Цей приклад досить простий, і, мабуть, було б простіше розмістити стан у програмі та передати його через реквізит. Однак, сподіваємось, це показує силу споживачів, які можуть отримувати доступ до даних незалежно від компонентів над ними у дереві.

Щоб дізнатись більше про React Context та інші чудові можливості React, ви можете приєднатися до списку очікування мого майбутнього вдосконаленого курсу React. Або якщо ви шукаєте більш дружніх для початківців, ви можете ознайомитися з моїм безкоштовним вступним курсом на React.

Щасливого кодування :)