Введение в Recoil

Вселенная, связанная с фронтенд-разработкой и особенно фронт-энд-разработкой на React, становится все более интересной с каждым днем.
Примерно месяц назад программное обеспечение Facebook предоставило открытый исходный код новой библиотеки управления состоянием для React. инженер Дэйв МакКейб.

Правильно, ребята, нового парня в блоке зовут Recoil. Он пришел прямо из кухни React и, похоже, здесь надолго. Довольно интересно, правда?

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

  • Recoil - это библиотека управления состоянием для React.
  • Он по-прежнему считается экспериментальным (не готовым к производству). Текущая версия - 0.0.8.
  • Он построен на всех последних новинках React, таких как Hooks и Suspense, и даже готов поддерживать параллельный режим (по крайней мере, согласно документации.
  • Библиотека небольшая, быстрая и практически не содержит шаблонов.

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

Прежде всего, установка

Первым шагом, конечно же, является установка библиотеки.

npm i recoil

or

yarn add recoil

Как я уже упоминал, Recoil не содержит шаблонов и позволяет легко начать работу. Вот:

Вот как легко настроить его в своем проекте и приступить к работе.

В этом примере я показал вам наиболее распространенный способ настройки Recoil, который находится в корневом компоненте вашего приложения, поэтому глобальное состояние будет доступно повсюду в вашем приложении. Но у вас есть возможность обернуть только части вашего приложения с помощью<RecoilRoot> и использовать глобальное состояние только там, где оно вам нужно. Круто, правда?

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

Все начинается с одного атома. Мне нравится, как Recoil позволяет мне использовать все метафоры химии и космоса в процессе разработки. Это просто заставляет все звучать еще круче.

Ага, атом ...

Что такое атом?

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

Как создать атом:

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

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

Как мы можем использовать атом в нашем компоненте?

Не волнуйтесь, создать атом так же просто. К счастью, в Recoil есть хороший набор предопределенных хуков, которые позволяют нам читать и писать в наш атом, если нам нужно.
Вот краткий список наиболее распространенных хуков, которые вы, вероятно, будете использовать:

  • useRecoilState(state), брат-близнец React.useState() - у вас есть значение состояния и установщик, который перезаписывает ваше текущее состояние.
  • useRecoilValue(state — С помощью этого хука вы получаете только текущее значение вашего состояния. Компонент, который использует этот крючок, автоматически подписывается на любые изменения состояния.
  • useSetRecoilState(state) - Как следует из названия, этот хук предназначен для использования только для обновления значения состояния без его чтения.

Хорошо, достаточно сухой теории. Давайте посмотрим на несколько примеров.

Как я уже упоминал, useRecoilState используется так же, как React.useState(). Я считаю, что многие из вас уже знают наизусть, как это работает. В этом примере greetMessage содержит текущее состояние атома, которое мы можем только читать, а с setGreetMessage мы можем обновить значение нашего состояния.

Как видите, следующие два хука, предоставленные Recoil, useRecoilValue и useSetRecoilState, являются своего рода разрушенными версиями useRecoilState.

С useRecoilValue мы получаем текущее состояние нашего атома и присваиваем его переменной greetMessage. Наверное, здесь приятно упомянуть, что / - переменная только для чтения, что означает, что мы не можем перезаписать ее каким-либо образом.
Для этого нам нужен / Hook, с помощью которого мы можем перезаписать или мутировать состояние.

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

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

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

Что такое селектор?

Согласно документам:

«Селекторы» представляют функцию или производное состояние в Recoil. Вы можете думать о них как о «чистой функции» без побочных эффектов, которая всегда возвращает одно и то же значение для данного набора значений зависимостей ».

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

Как всегда, я чувствую, что пример сделает вещи более понятными.

Хорошо, так что у нас здесь? Давайте прочитаем файл сверху вниз:

  • Сначала импортируем селектор из Recoil.
  • Затем мы импортируем наше текущее состояние, которое удерживает атом greetings.
  • Затем мы определяем наш селектор greetingsMike и творим с ним волшебство.

На первый взгляд селектор немного похож на атом. У нас есть ключ, который снова должен быть уникальным значением, но вместо значения по умолчанию у нас есть геттер. Как видно из примера, геттер используется для получения текущего состояния, которое удерживает атом greetings. И мы используем результат текущего состояния, чтобы вернуть новое приветствие; в этом случае возвращаемое значение будет строкой «Hello Mike».

Как использовать селектор в нашем компоненте

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

В дополнение к тому, что было раньше в компоненте <Hello>,
теперь мы импортируем наш вновь созданный селектор и используем его. Когда мы видим выходные данные этого компонента, мы увидим поле ввода со значением по умолчанию Hello и приветственное сообщение «Hello Mike».

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

Как перезаписать и изменить состояние с помощью селектора

На самом деле это действительно просто. Вот пример:

Опять же, у нас есть та же настройка селектора, с той лишь разницей, что вместо геттера на этот раз мы используем другую встроенную функцию, которая есть у селектора: сеттер.

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

В этом примере мы делаем то же самое, что и в примере выше с геттером, но на этот раз мы изменяем состояние напрямую с помощью метода set.

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

Потрясающие! И последнее, но не менее важное: я хотел бы показать вам несколько асинхронных примеров как атомов, так и селекторов.

Асинхронные примеры атомов и селекторов

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

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

Вот CodeSandbox ссылка на проект, чтобы проверить и поиграть с ним.

Быстрый просмотр файла:

  • Во-первых, мы импортируем наш атом searchStringState, который, как вы могли догадаться, содержит строку поиска, введенную пользователем.
  • Затем используемый нами геттер находится в асинхронной функции обратного вызова, которая извлекает Giphys.
  • И в качестве последнего шага мы возвращаем результат вызова API.

Вот как выглядит компонент, который отображает полученный файл Giphys:

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

Когда мы используем асинхронные обратные вызовы в селекторе или атоме, родительский компонент, который их использует, должен быть заключен в резервный элемент Suspense. Как это круто! Здесь мы ясно видим, что Recoil на самом деле уже использует новейшие функции React, и они глубоко интегрированы в библиотеку.

А вот как мы можем воспользоваться атомом, который асинхронно извлекает некоторые ресурсы.

Заключительные слова и мысли об отдаче

Время, которое я потратил на игру с Recoil, привело к созданию небольшой игры,
которую я назвал Brain-teaser, проверочного концептуального приложения, в которой я попытался быстро проверить, на что действительно способен Recoil.

Не стесняйтесь проверить это и поиграть с ним на Github или опробовать развернутую версию здесь.

На данный момент мое лучшее время - 20 секунд - попробуйте превзойти это!

До сих пор я старался избегать прямого сравнения с другими библиотеками управления состоянием, которые у нас есть. Я считаю, что в зависимости от варианта использования разные библиотеки могут иметь преимущества перед другими, и хорошо иметь несколько из них на выбор.

Что мне действительно нравится в Recoil, так это то, что он кажется действительно быстрым, с него легко начать работу и, что наиболее важно для меня, он действительно точно настроен и адаптирован для React. Я легко вижу Recoil как серебряную подкладку между Context AP I и Redux.

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

В общем, библиотека все еще кажется очень молодой, а документация не очень тщательной - их даже кое-где не хватает. Тем не менее, я очень положительно отношусь к Recoil и с нетерпением жду возможности увидеть, как этот проект будет развиваться со временем.

Это с моей стороны. Удачи кодированию!