React Context за 5 минут: что это и как использовать
Что такое React Context и как с ним работать? Быстрый и понятный разбор на примере.
73К открытий75К показов
React Context для многих стал привычным способом управления состоянием, заменив собой Redux. В этой статье вы узнаете о React Context и научитесь его использовать.
Рассмотрим работу Context на примере такого дерева. Нижние блоки можно представить как отдельные компоненты:
Допустим, вам нужно добавить свойство какому-то из нижних блоков — это несложно. Но что делать, если это свойство нужно передать соседнему (т. е. отдельному) блоку? Пока единственное решение — передать это свойство блоку-родителю, откуда его можно передать необходимому дочернему блоку.
Если вдруг вам понадобится передать свойство соседнему родителю, вы, опять же, просто переносите его на уровень выше, а потом «спускаете» обратно к нужному блоку.
Решение довольно простое, а главное — рабочее. Но что делать, если нужно передать свойство дальнему блоку?
Для этого нужно «поднять» свойство по всему дереву вверх до самого первого блока, а потом «спустить» обратно к нужному дочернему блоку. Проблема в том, что это свойство будет проходить через кучу промежуточных компонентов. Этот утомительный и трудоёмкий процесс известен как пробрасывание (англ. prop drilling).
Именно на этом этапе задействуется Context API. Он даёт возможность передавать свойства отдельным блокам дерева без сложных манипуляций с родительскими и дочерними блоками.
В качестве примера использования React Context возьмём вот такой забавный переключатель дня и ночи:
Полный код можно посмотреть здесь.
Создание Context
Вначале нужно сделать так, чтобы всё приложение имело доступ к Context. Для этого в index.js
нужно обернуть всё приложение в ThemeContext.Provider
. Ещё стоит передать ему свойство value
. В нём будет храниться состояние: день или ночь.
Получение свойств от Context через contextType
Пока что в App.js
возвращается компонент <Image />
.
Нам нужно с помощью Context менять className
в Image.js
с Day
на Night
и обратно. Для этого нужно добавить к компоненту статическое свойство ContextType
. Потом, используя интерполяцию строки, нужно передать это свойство в className
в объекте <Image />
.
Теперь свойство className
содержит строку из value
:
Получение свойств из Context
К сожалению, способ выше работает только с классовыми компонентами. Но благодаря хукам с помощью функциональных компонентов теперь можно сделать всё что угодно. Так что для полноты картины нужно конвертировать имеющиеся компоненты в функциональные и использовать ThemeContext.Consumer
, чтобы передать информацию между ними.
Это можно сделать, обернув элементы в экземпляр <ThemeContext.Consumer>
. Внутри него нужно предоставить функцию, возвращающую элементы. В данном случае будет использоваться паттерн «render props», который позволяет передать компоненту в качестве children любую функцию, которая возвращает JSX код.
Примечание <Button />
тоже нужно обернуть в <ThemeContext.Consumer>
— в будущем это добавит функциональности кнопке.
Вынесение свойств из Context
На текущем этапе в приложении передаётся заранее прописанное значение, но наша цель — переключать день и ночь кнопкой. Для этого нужно переместить <Provider>
в отдельный файл и обернуть его в собственный компонент ThemeContextProvider
.
Примечание Теперь свойство value
обрабатывается и в новом файле ThemeContext.js
, поэтому обработку этого значения из файла index.js
нужно убрать.
Изменение Context
Чтобы подвязать кнопку, сначала нужно добавить состояния state
в ThemeContextProvider
:
Потом нужно добавить метод переключения между днём и ночью:
После этого нужно изменить значение value
на this.state.theme
, чтобы свойство устанавливалось из состояния:
Теперь нужно изменить value
на объект, содержащий {theme: this.state.theme, toggleTheme: this.toggleTheme}
, а также заменить использование value
на получение поля theme
из объекта. То есть нужно каждое theme
заменить на context
, а каждую ссылку на theme
— на context.theme
.
И под конец на кнопку нужно повесить слушатель события onClick
. При нажатии кнопки должен вызываться context.toggleTheme
— в таком случае будут обновляться Consumer’ы, которые используют состояние от Provider’ов. Код кнопки будет выглядеть примерно так:
Теперь эта кнопка переключает день и ночь.
Рекомендации к работе с Context
Хоть в этом коде всё работает отлично, всё же есть некоторые аспекты с работой Context:
- Не используйте Context, если он заменяет пробрасывание всего на один-два уровня. Этот инструмент — отличный способ, если нужно распространить состояние на множество компонентов, находящихся в «дереве» далеко друг от друга. Но если вам нужно просто опуститься или подняться на пару уровней, то пробрасывание будет легче и быстрее.
- Постарайтесь не использовать Context для сохранения локального состояния. Например, если вам нужно сохранить введённые в форму данные, то лучше использовать локальное свойство.
- Всегда оборачивайте родителя в Provider’а на как можно более низком уровне — не стоит использовать самую верхушку «дерева».
- Наконец, если вы решили пересылать свойства таким способом, важно помнить про наблюдение за производительностью и рефакторингом. Но это скорее всего не понадобится, если просадки в производительности не будут сильно заметны.
Подумываете освоить или освежить знания по React? Тогда держите дорожную карту по React-разработке.
73К открытий75К показов