Как стать автором
Обновить

Шэрим стейт между хуками в React

Время на прочтение3 мин
Количество просмотров5.2K

Всем привет! Меня зовут Слава, сейчас работаю в Samsung Next, ранее в Yandex, уже 4 года занимаюсь активным созданием своих библиотек в Open Source, и сейчас я расскажу что удивило и продолжает удивлять меня уже полтора года!

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

Я научился подменять логику хуков React) И обнаружил что это уже используется в девелоперских тулзах при сборе информации о вызванных хуках и даже более того, Preact в compat режиме тоже предоставляет эквивалентные возможности.

В этот момент я уже работал в Samsung Next и активно участвовал в формировании архитектуры проекта и меня восхищало решение принятое на проекте, о том, что вместо DI мы будет использовать Service Provider. Это обозначало, что теперь имея функцию фабрику с логикой или класс, можно из любого места приложения получить методы нужной логики и данные состояния.

И трам-парам как по-фолшебству, как в новогоднюю ночь, проявился код. Я подумал ведь можно же управлять состоянием приложения на React используя всего один дополнительный хук!

Идея была такой, а что если представить что функция хука это Service Provider, причем поставляет она очень интересный сервис. Он может содержать реактивную логику через useEffect, может кешировать нагруженные вычисления через useMemo, а благодаря useState мы определяем его состояние!

Посмотрите как красиво смотрится такой сервис:

const useCounter = () => {
    const [counter, setCounter] = useState(0)
    const inc = () => setCounter(v => v + 1)

    return {
        counter,
        inc
    }
}

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

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

А вот так будет смотреться синхронизация данных состояния и локального хранилища браузера.

const useDark = () => {
    const [dark, setDark] = useState(
        localStorage.getItem('dark') === 'on'
    )

    useEffect(() => {
        localStorage.setItem('dark', dark ? 'on' : 'off')
    }, [dark])

    return {
        dark,
        setDark
    }
}

И здесь мы инкапсулировали даже реактивное выражение! При каждом изменении значения dark, будет производиться его синхронизация. Как вы уже заметили это переключалка ночной темы, теперь благодаря Service Provider можно использовать это состояние в каком угодно компоненте и все они будут использовать одно состояние.

Все оказалось предельно просто и понятно, и теперь благодаря всего одному хуку, можно создать прикольную штуку)

const Counter = () => {
  const { counter } = useBetween(useCounter);

  return <p>{counter}</p>;
}

const Button = () => {
  const { inc } = useBetween(useCounter);

  return (
    <button onClick={inc}>+</button>
  )
}

const App = () => (
  <>
    <Counter />
    <Button />
    <Counter />
    <Button />
  </>
)

Глянуть этот код в работе можно на Codesandbox по этой ссылке.

Мы создали минимальное React приложение в котором между четырьмя компонентами делится один счетчик.

Правда! Выглядет реально круто! То есть мы такие взяли и внедрили общее состояние для двух разных React компонентов. Никакого кода в новом стандарте, только хуки.

Хук становится идентификатором сервиса, а сам сервис создается только при вызове useBetween. Иными словами теперь мы можем пользоваться результатом вызова хука между компонентами.

Так же очень подкупает тот факт что по сути ничего не нужно учить нового, ты просто используешь хуки между компонентами и хранишь там состояние о пользователе, покупках, да всё что угодно.

Но к сожалению не все хуки React можно переиспользовать, например useContext оказался крепким орешком. Внутри React нет возможности подписаться на контекст вне React компонента, а именно там как раз и создаётся общее состояние, за пределами компонента нет и контекста.

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

В итоге получилось элегантное решение для написания небольших и среднего размера проектов. Для больших проектов я всё же порекомендовал бы брать что-то более популярное, так как будет довольно сложно найти большое количество специалистов в use-between)

https://www.npmjs.com/package/use-between
https://github.com/betula/use-between

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Захотелось воспользоваться?
15.69% Очень интересно!8
17.65% Классная штука9
17.65% Что-то новенькое)9
35.29% Ничего привлекательного18
13.73% Не понял(7
Проголосовал 51 пользователь. Воздержались 11 пользователей.
Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 5: ↑2 и ↓3-1
Комментарии28

Публикации

Истории

Работа

Ближайшие события

Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
OTUS CONF: GameDev
Дата30 мая
Время19:00 – 20:30
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область