Что такое контекст?
С точки зрения неспециалиста, контекст означает «ситуацию, в которой что-то происходит или из-за которой что-то происходит».

Значение контекста в React
Согласно приведенному выше определению, React Context обеспечивает инкапсуляцию, в которой происходит изменение переменной, и мы получаем доступ к одной и той же переменной в том же контексте. Здесь важно отметить, что эта инкапсуляция может содержать несколько компонентов и, таким образом, может помочь в совместном использовании переменных между компонентами или распространении переменных сверху вниз или наоборот.

Давайте попробуем реализовать базовый сценарий, чтобы лучше понять это.

Случай использования

Мы собираемся реализовать базовое приложение счетчика.

После того, как пользователь нажмет кнопку «Увеличить счетчик», значение счетчика увеличится на 1.

Здесь важно отметить, что кнопка и заголовок, отображающие значение, находятся в разных компонентах, и мы делимся значением между компонентами в режиме реального времени.

Давайте посмотрим, как реализовать вариант использования

  • Сначала мы сделаем базовые строительные леса реагирующего приложения.
npx create react-app counter template=typescript

Команда выше создаст одно базовое приложение React.

Далее мы создадим два основных компонента.

Компонент заголовка

// Header.tsx

const Header = () => {
    return(
        <h1>Counter value is </h1>
    )
}

export default Header;

Компонент тела

// Body.tsx

const Body = () => {
    const incCounter = () => {
        
    }
    return(
        <button onClick={incCounter}>
            Increase Counter
        </button>
    )
}

export default Body

Обновите App.tsx, удалив весь код в блоке возврата с помощью

// App.tsx
 
return (
    <>
      <Header/>
      <Body/>
    </>
  );

У нас есть базовая структура, и теперь мы углубимся в реализацию контекста.

  1. Создайте файл с именем CounterContext.tsx и добавьте приведенный ниже код.
import { createContext, useState } from "react";

// Step 1
const CounterContext = createContext({
counter : 0,
handleCounter : () => {}
});

// Step 2
const CounterProvider = ({children}:{children:any}) => {
// Step 3
const [counter,setCounter] = useState(0);
//Step 4
const handleCounter = () => {
setCounter((prevValue:any) => prevValue + 1);
}
//Step 5
const counterObj = {counter,handleCounter}
// Step 6
return(
<CounterContext.Provider value={counterObj}>
{children}
</CounterContext.Provider>
)
}
// Step 7
export { CounterProvider , CounterContext}

Не пугайтесь большого количества строк кода, так как это основная суть контекста, и мы рассмотрим каждую строку шаг за шагом.

  1. На шаге 1 мы создали контекст с помощью createContext с именем counterContext. createContext — это метод, предоставляемый реакцией, который помогает создать контекст, в котором инкапсулированы все компоненты, где есть необходимость доступа или совместного использования переменных. методы, к которым нам нужно получить доступ в инкапсулированных компонентах, например. в нашем примере переменная счетчика и метод handleCounter выставлены.
  2. Контекст, созданный на шаге 1, имеет компонент реагирования Provider. Преимущество использования этого провайдера заключается в том, что он дает оболочку, вокруг которой мы можем обернуть все компоненты, в которых мы хотим подписаться на изменения контекста. Здесь, на шаге 2, мы создали функцию с именем CounterProvider, которая возвращает компонент ответного поставщика.
  3. На шаге 3 мы просто создали переменную-счетчик с хуком useState и сеттером для того же с помощью setCounter.
  4. На шаге 4 мы создали метод handleCounter, который активирует установщик для переменной счетчика.
  5. Шаг 5 — это реальный бизнес, где мы определяем свойства, методы, которые нам нужно предоставить компонентам, вокруг которых мы обернули Provider. Обратите внимание, что структура объекта, определенная на шаге 1, должна совпадать со структурой объекта, определенной здесь, иначе вы получите ошибку несоответствия типа. Вы можете думать о структуре, определенной на шаге 1, как о псевдониме, а о структуре, определенной на шаге 5, как о реальной реализации.
  6. Компонент реакции поставщика, возвращенный на шаге 2, нуждается в свойстве значения, в которое мы передаем объект, определенный на шаге 5, чтобы то же самое могло быть доступно во вложенных компонентах.
  7. Наконец, на шаге 7 мы экспортируем созданный контекст и провайдер, чтобы к ним можно было получить доступ извне.

С помощью вышеупомянутого шага мы закончили реализацию нашего CounterContext, и в большинстве случаев это основные 7 шагов, которые необходимы, сложный вариант использования и сложность могут варьироваться.

Теперь давайте используем этот созданный контекст для реализации нашего варианта использования.

  • Как только у нас будет готов компонент CounterProvider, мы будем использовать его в App.tsx и обернем его вокруг компонентов Header и Body, как показано ниже. Мы обернем Provider вокруг компонентов, в которых мы хотим получить доступ к контексту.
 return (
    <CounterProvider>
      <Header/>
      <Body/>
    </CounterProvider>
  );

Давайте внесем изменения в компонент Body, чтобы инициировать изменение переменной счетчика.

  • Компонент тела
import { useContext } from "react";
import { CounterContext} from './CounterContext';

const Body = () => {

const { handleCounter} = useContext(CounterContext); // Step 1
const incCounter = () => {       // Step 2
handleCounter();
}
return(
<button onClick={incCounter}>
Increase Counter
</button>
)
}

export default Body
  1. На шаге 1 мы используем API useContext, предоставленный React. Он принимает аргумент, который является именем контекста. Как только мы передадим имя контекста, он вернет объект или свойство, переданное в свойстве value, при возврате компонента Provider. В нашем случае это будет так —
 <CounterContext.Provider value={counterObj}>
            {children}
        </CounterContext.Provider>

Мы получаем свойство handleCounter с помощью деструктурирования.

2. На шаге 2 мы вызываем handleCounter при нажатии кнопки. Если вы помните, метод handleCounter — это тот, в котором мы устанавливаем новое значение счетчика с помощью setCounter. Таким образом, при нажатии на кнопку переменная счетчика в контексте обновляется.

Теперь давайте внесем изменения в компонент заголовка, чтобы подписаться на изменения, внесенные в переменную счетчика.

  • Компонент заголовка

Как только значение обновляется производителем, нам нужно использовать то же значение в другом компоненте. Давайте внесем некоторые изменения в компонент Header для того же.

import { useContext } from "react";
import { CounterContext } from "./CounterContext";
const Header = () => {
const { counter } = useContext(CounterContext);   // Step 1 
return(
<h1>Counter value is - {counter}</h1>           // Step 2 
)
}
export default Header;
  1. На шаге 1 мы снова используем API useContext, и на этот раз мы получаем переменную счетчика, которая является обновленным значением после нажатия кнопки в компоненте Body.
  2. На шаге 2 мы отображаем переменную счетчика.

Вкратце это то, как мы можем использовать Context и useContext API для передачи значения от одного компонента к другому в React.

Вы можете найти полный фрагмент кода в repo.

Дайте мне знать в ответ, если у вас есть какие-либо дополнительные вопросы.

Обо мне — я энтузиаст программирования, который любит читать и писать о внешнем дизайне, JavaScript и вещах, связанных с UI/UX. Нажмите здесь, чтобы прочитать все мои статьи и дайте мне знать ваши отзывы.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord . Заинтересованы в хакинге роста? Ознакомьтесь с разделом Схема.