В прошлом я обычно обращался к библиотекам, таким как MobX или Redux, чтобы управлять состоянием в моем приложении и предоставлять значения, к которым я хочу получить доступ глобально, во всем моем приложении. Это избавляет меня от необходимости передавать вещи через реквизиты, а также отделяет повторно используемые данные и действия от простой логики на уровне компонентов. Новый Context API React представляет собой простое решение для таких небольших случаев использования. По-прежнему бывают случаи, когда Redux и MobX - правильный ответ, но во многих случаях использование React Context API может выполнить свою работу.
В этом посте я собираюсь сделать базовое введение в контекст и короткую демонстрацию того, как инициализировать контекст со значениями, а затем получить доступ к этим значениям в другом месте моего приложения.
Я создаю это на своей площадке для сборников рассказов, чтобы не запускать совершенно новое приложение. Вы можете прочитать, как я создал эту среду, в одном из моих предыдущих сообщений в блоге:
Что такое API контекста React?
Контекст предоставляет способ передавать данные через дерево компонентов без необходимости передавать реквизиты вручную на каждом уровне. - Документация React JS
Это наиболее полезно, когда у вас есть глобальные данные, которые многие компоненты захотят использовать, такие как атрибуты темы, пользовательские данные и т. Д.
Использование контекста состоит из трех основных шагов:
- Создание вашего контекста
- Предоставление его вашему приложению
- Потребление во вложенном компоненте
Теперь давайте создадим простое приложение, которое отображает сообщение во вложенном компоненте.
Это будет иметь больше смысла по мере того, как мы рассмотрим детали, но в качестве обзора: в этом примере я собираюсь визуализировать Component1
, который будет отображать Component2
, который будет отображать Component3
. Component1
будет там, где приложению предоставляется контекст, а Component3
- там, где будет использоваться контекст.
Шаг 1. Создайте свой контекст
Сначала вы должны определить значение по умолчанию для вашего контекста. Это используется только в том случае, если вы пытаетесь использовать свой контекст за пределами вашего провайдера. Чтобы упростить это, мое значение по умолчанию также будет моим начальным значением, которое будет иметь больше смысла на следующем шаге. Но пока в приведенном ниже коде вы можете увидеть определенный объект initialValue
. Этот объект отвечает за хранение пар ключ-значение вашего контекста. В этом случае просто сообщение, которое представляет собой строку.
const initialValue = { message: "This is my message from context"} export const MyContext = React.createContext(initialValue)
Шаг 2. Укажите это значение своему приложению
Затем нам нужно сообщить нашему приложению, что это за значение, и в этом случае мы собираемся предоставить ему указанное выше initialValue
. Вы можете сделать это, обернув компонент, который содержит часть вашего приложения, для которой вы хотите иметь доступ к этой информации. Например, если у вас есть какие-то пользовательские данные, о которых нужно знать только вашему navBar
, вы можете заключить только navBar
в контекст, специфичный для пользовательских данных.
В этом примере мы хотим обернуть компонент верхнего уровня (Component1
) Provider
, содержащим мое начальное значение. Я сделал это, реализовав следующее:
export const Component1 = () => ( <MyContext.Provider value={initialValue}> <HomeWrapper> <h1>This is Component 1</h1> <Component2 /> </HomeWrapper> </MyContext.Provider> )
Шаг 3. Воспользуйтесь ценностью вашего контекста
Последний шаг - использовать значение вашего приложения в дочернем компоненте вашего Provider
. Это достигается путем обертывания потребляющего дочернего компонента потребителем вашего контекста, к которому можно получить доступ, импортировав ваш контекст и отрендерив его потребителя, например <MyContext.Consumer></MyContext.Consumer>
.
Как только вы попадаете в Consumer
, я использую шаблон рендеринга реквизита, чтобы получить доступ к значению моего контекста. Я также могу деструктурировать значение и вводить только те ключи моего объекта значения, которые мне нужны.
См. Код ниже для фактической реализации.
import { MyContext } from './Component1' const Component3 = () => ( <MyContext.Consumer> {({message}) => <> <h3>Component 3</h3> message: <h3>{message}</h3> </>} </MyContext.Consumer> )
Если вы хотите узнать больше о Render Props, ознакомьтесь с моим сообщением в блоге по этой теме. Ссылка в конце статьи.
Удивительный! Теперь давайте посмотрим, как это работает, и снизим ли мы значение нашего сообщения до Component3
. Мы можем проверить это, используя Storybook, чтобы создать историю для Component1
и посмотреть, отображает ли он значение контекста во вложенном Component3
. Моя история написана так:
import React from 'react' import { storiesOf } from '@storybook/react' import { Component1 } from './Component1' storiesOf('Context API Project', module) .add('Component1', () => <Component1 />)
а затем должен вывести что-то вроде снимка экрана ниже:
Ура! Теперь мы видим, что сообщение, которое было определено в initialValue
из MyContext
, отображается в Component3
. Успех!
Теперь представьте себе все варианты использования для этого и почему это полезно ... Следуя принципу единой ответственности, мы выделили хранилище этой информации и позволили контексту отвечать за нее, в то время как компоненту просто нужно беспокоиться о ее потреблении. и отображать его. Это обеспечивает большую возможность повторного использования нашего компонента, поскольку я могу изменить контекст, а затем он может отображать другое сообщение.
В случае создания контекста темы у вас может быть несколько тем как набор значений шрифтов, цветов и т. Д. Для различных брендов или стилей. Затем, чтобы изменить отображение компонента, вам нужно будет изменить значение в вашем провайдере на другую тему. Поскольку все вложенные компоненты зависят только от значения контекста, ничего не запрограммировано жестко и не требует переопределения.
Для дальнейшего пояснения я полностью включил код этого проекта ниже:
Ресурсы: