Новый контекст Реакта

или жизнь без боли и бойлерплейта

Владимир Цибизов
3 min readJun 28, 2018

Предисловие и боль

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

Я достаточно давно пишу на стеке React-экосистемы и для управления глобальным состоянием использую Redux. Первое время я был вдохновлён тем, как просто и здорово всё получается. Сначала я писал всё в отдельных файлах: actions.js, constants.js, reducer.js и так далее. Потом мне надоело ходить из папки в папку и я начал использовать подход ducks, но с каждым новым редьюсером мне всё меньше нравилось писать бойлерплейт.

Я начал чувствовать, что пишу одно и то же, что каждый раз мне нужно написать action type, затем action creator, добавить action type в редьюсер и подключить всё в коннекте контейнера – и так по бесконечному кругу. Появилась потребность в абстракциях: тогда уже была выпущена библиотека redux-actions, но мне никогда не нравились подходы, которые могут связать мне руки. Это казалось полумерой и не решало моих проблем.

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

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

Краткий обзор нового подхода

Тем, кто ещё не до конца знаком с новым контекстом, советую прочитать статью Кента Додса, где доступно объясняется суть обновления. Также есть официальная документация с примерами.

На самом деле всё просто:

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

Сделаем жизнь разработчика проще

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

Вместо того, чтобы каждый раз импортировать консьюмер для использования контекста, проще создать универсальный HOC. А ещё было бы удобно собрать всех провайдеров в одном месте и подключать их из этого файла в наше приложение.

В итоге я хотел получить что-то такое же простое, как коннект Redux:

connect(mapStateToProps, mapDispatchToProps)(Component)

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

withContext('My')(Component)

И всё! Остальное берёт на себя провайдер.

Так я это реализовал:

Реализация самого провайдера:

А вот как это удобно использовать:

И больше не надо писать action type, action creator и reducer.

Больше не надо импортировать всё это и подключать в коннекте.

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

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

Выводы

Я согласен, что далеко не все кейсы подходят для использования нового контекста, и есть много асинхронных вещей, которые пока реализуются только с помощью redux-saga или redux-thunk.

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

В своём примере я разобрал только работу с запросами данных, но контекст можно использовать и в других местах, таких как: авторизация, темы или общее состояние для разных частей приложения.

Вот как я вижу работу с состоянием приложения на текущий момент:

  • данные нужны один раз в одном месте – setState
  • данные нужны в нескольких местах – context
  • сложные кейсы с асинхронными запросами – redux/saga/thunk/etc.

Гитхаб:

Рабочая демка:

Подписывайтесь на канал, ставьте лайки, хлопайте статье (или нет).

Твиттер, GitHub, Telegram.

--

--