Найти в Дзене
Янис Балаев

Руководство по React Context и useContext ()

Контекст React предоставляет данные компонентам независимо от того, насколько глубоко они находятся в дереве компонентов
В этом посте вы узнаете, как использовать концепцию контекста в React.
Оглавление 1. Как использовать контекст Для использования контекста в React требуется 3 простых шага: создание контекста(A), предоставление контекста(Б) и использование контекста(В).
А. Создадим контекст Заводская функция принимает один необязательный аргумент: 'Любое значение' Б. Предоставление контекста
Компонент Context.Provider - доступный в экземпляре контекста, используется для предоставления контекста его дочерним компонентам, независимо от их глубины. Опять же, здесь важно то, что все компоненты, которые позже захотят использовать контекст, должны быть заключены в компонент провайдера. В. Использование контекста Использование контекста может быть выполнено двумя способами. Первый способ - это использовать хук
Оглавление

Перевод статьи

Контекст React предоставляет данные компонентам независимо от того, насколько глубоко они находятся в дереве компонентов

В этом посте вы узнаете, как использовать концепцию контекста в React.

Оглавление

  • 1. Как использовать контекст
  • 2. Когда он вам пригодится?
  • 3. Пример использования (имя пользователя)
  • 3.1 Контекст на помощь
  • 3.2 Когда контекст меняется
  • 4. Обновление контекста
  • 5. Вывод

1. Как использовать контекст

Для использования контекста в React требуется 3 простых шага: создание контекста(A), предоставление контекста(Б) и использование контекста(В).

А. Создадим контекст

Встроенная фабричная функция createContext (по умолчанию) создает экземпляр контекста
Встроенная фабричная функция createContext (по умолчанию) создает экземпляр контекста

Заводская функция принимает один необязательный аргумент: 'Любое значение'

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

Чтобы установить значение контекста, используйте свойство value, доступное в <Context.Provider value = {value} />
Чтобы установить значение контекста, используйте свойство value, доступное в <Context.Provider value = {value} />

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

В. Использование контекста

Использование контекста может быть выполнено двумя способами. Первый способ - это использовать хук useContext (Context)

Хук возвращает значение контекста: value = useContext (Context).
Хук возвращает значение контекста: value = useContext (Context).

Хук также гарантирует повторный рендеринг компонента при изменении значения контекста

Второй способ - использовать функцию рендеринга, предоставленную в качестве дочернего для специального компонента Context.Consumer, доступного в экземпляре контекста:

Опять же, в случае, если значение контекста изменится -  <Context.Consumer> повторно отрендерит свою функцию рендеринга.
Опять же, в случае, если значение контекста изменится - <Context.Consumer> повторно отрендерит свою функцию рендеринга.
-5

Вы можете иметь столько дочерних компонентов, сколько хотите для одного контекста. Если значение контекста изменяется (путем изменения свойства value провайдера (<Context.Provider value = {value} />), то все дочерние компоненты немедленно уведомляются и повторно обрабатываются. Если дочерний компонент не заключен внутри провайдера, но все же пытается получить доступ к значению контекста (используя useContext (Context) или <Context.Consumer>), то значение контекста будет аргументом значения по умолчанию, предоставленным createContext (defaultValue) фабричная функция, создавшая контекст.

2. Когда он вам пригодится?

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

Вы можете держать внутри контекста:

  • Глобальное состояние приложения
  • Тема приложения
  • Конфигурация приложения
  • Аутентификация пользователя
  • Пользовательские настройки
  • Предпочтительный язык
  • Набор услуг

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

  • Во-первых, интеграция контекста добавляет сложности. Создание контекста, обертывание всего в провайдере, использование useContext () в каждом дочернем компоненте - это увеличивает сложность.
  • Во-вторых, добавление контекста затрудняет модульное тестирование компонентов. Во время модульного тестирования вам придется заключить потребительские компоненты в поставщик контекста. Включая компоненты, на которые косвенно влияет контекст - родителей дочерних компонентов контекста!

3. Пример использования (имя пользователя)

Самый простой способ передать данные от родителя к дочернему компоненту - это когда родитель назначает реквизиты своему дочернему компоненту

т.к. пишу на TS - Props обьявил ранее и назначил тип имени - строкой
т.к. пишу на TS - Props обьявил ранее и назначил тип имени - строкой

Родительский компонент <App /> назначает данные userName своему дочернему компоненту <UserInfo name = {userName} /> с помощью свойства userName.

Это обычный способ передачи данных с использованием реквизита. Вы можете использовать этот подход без проблем. Ситуация меняется, когда дочерний компонент <UserInfo /> не является прямым потомком <Application />, но содержится в нескольких предках. Например, предположим, что компонент <Application /> (тот, у которого есть глобальные данные userName) отображает компонент <Layout />, который, в свою очередь, отображает компонент <Header />, который, в свою очередь, в конечном итоге отображает компонент <UserInfo /> (который хотел бы получить доступ к имени пользователя).

Посмотрим как это будет выглядеть

-7

Вы можете видеть проблему: поскольку компонент <UserInfo /> отображается глубоко в дереве, и все родительские компоненты (<Layout /> и <Header />) должны передавать свойство userName.

Эта проблема также известна как Буровая установка.

Контекст React - возможное решение. Давайте посмотрим, как его применить в следующем разделе.

3.1 Контекст на помощь

Напоминаем, что для применения контекста React требуются 3 участника: контекст, провайдер, извлеченный из контекста, и дочерний компонент.

Вот как будет выглядеть пример приложения при применении к нему контекста
Вот как будет выглядеть пример приложения при применении к нему контекста

Во-первых, const UserContext = createContext ('Unknown') создает контекст, в котором будет храниться информация об имени пользователя.

Во-вторых, внутри компонента <App /> дочерние компоненты приложения заключены в контекст пользователя: <UserContext.Provider value = {userName}>. Обратите внимание, что свойство value компонента поставщика важно: именно так вы устанавливаете значение контекста.

Наконец, <UserInfo /> становится потребителем контекста с помощью встроенной ловушки useContext (UserContext). Хук вызывается с контекстом в качестве аргумента и возвращает значение имени пользователя.

Промежуточные компоненты <Layout /> и <Header /> не должны передавать свойство userName. В этом большое преимущество контекста - он снимает бремя передачи данных через промежуточные компоненты.

3.2 Когда контекст меняется

Когда значение контекста изменяется путем изменения свойства значения поставщика контекста (<Context.Provider value = {value} />), тогда все его потребители уведомляются и повторно обрабатываются. Например, если я изменю имя пользователя с «Дэн Абрамов» на «Дэн, Дэн Абрамов», то потребитель <UserInfo /> немедленно выполнит повторный рендеринг, чтобы отобразить последнее значение контекста

-9

4.Обновление контекста

React Context API по умолчанию не имеет состояния и не предоставляет специальный метод для обновления значения контекста из компонентов-потребителей.

Но это можно легко реализовать, интегрировав механизм управления состоянием (например, хуки useState () или useReducer ()) и предоставив функцию обновления прямо в контексте рядом с самим значением. В следующем примере компонент <App /> использует ловушку useState () для управления значением контекста.

-10

<UserNameInput /> потребитель считывает значение контекста, из которого извлекаются userName и setUserName. Затем потребитель может обновить значение контекста, вызвав функцию обновления setUserName (newContextValue)

<UserInfo /> - еще один потребитель контекста. Когда <UserNameInput /> обновляет контекст, этот компонент также обновляется.

Обратите внимание, что <App /> запоминает значение контекста. Мемоизация сохраняет объект значения контекста одним и тем же до тех пор, пока userName остается неизменным, предотвращая повторную визуализацию потребителей каждый раз, когда повторно отображается <App />. В противном случае, без мемоизации, const value = {userName, setUserName} создаст разные экземпляры объекта во время повторного рендеринга <App />, инициируя повторный рендеринг в потребителях контекста.

5. Вывод

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

Для использования контекста требуется 3 шага: создание, предоставление и использование контекста. При интеграции контекста в ваше приложение учтите, что он значительно усложняет его. Иногда "прокинуть" пропсы через 2-3 уровня иерархии не составляет большой проблемы.

Спасибо Дмитрий Павлютин