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

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

React предложил решение этой проблемы, которое называется Context.

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

Возьмем для этого пример.

const AComponent = ({message}) =>{
  return <div><BComponent /></div>
}
const BComponent = ({message}) =>{
  //we want to display messageForB here.
  return <div>{message}</div>
}
export default function App() {
  const [message, setMessage] = useState('Hello world!');
  return (
    <div className="App">
      <AComponent message={message}  />
    </div>
  );
}

Как вы можете видеть в приведенном выше примере, у нас есть часть данных message, которую мы хотим отобразить только в BComponent. В AComponent он не нужен, но все же из-за однонаправленного потока данных мы должны пропускать его через AComponent.

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

Так как же Context решает эту проблему. Давайте взглянем.

Давайте сначала создадим объект контекста:

const MessageContext = React.createContext('A default message!');

Этот оператор создает объект контекста со значением по умолчанию. Теперь этот объект контекста поставляется с компонентом Provider. Компонент Provider позволяет компонентам, которые используют эти данные, подписаться на изменения в данных контекста.

<MessageContext.Provider value={"Hello world!"}>

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

const BComponent = () =>{
  const message = useContext(MessageContext);
  return (<div> B Component : {message}</div>);
}

Вот и все!. Теперь у вас есть данные, доступные в вашем дочернем компоненте, без необходимости передавать их через реквизиты.

Весь ваш код должен выглядеть так.

import React, { useState, useContext } from "react";
const AComponent = () =>{
  return <BComponent />
}
const BComponent = () =>{
  const message = useContext(MessageContext);
  return (<div> B Component : {message}</div>);
}
const MessageContext = React.createContext('A default message');
export default function App() {
  const [message, setMessage] = useState('Hello world!');
  return (
    <div className="App">
      <MessageContext.Provider value={message}>
          <AComponent />
      </MessageContext.Provider>
    </div>
  );
}

Это круто. не так ли? Но React предлагает избегать частого использования Context. Потому что, согласно React Docs, это затрудняет повторное использование компонента.

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

Подробнее о Context можно прочитать в документации по реакции здесь.