Pull to refresh

Управление состоянием в React приложениях

Reading time3 min
Views7.2K

Всем привет!

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

А что если я расскажу как это можно сделать быстро и просто?

Введение

Буквально каждую конференцию мы слышим от спикеров, а вы знаете как работают контексты? а вы знаете что каждый ваш слушатель перерисовывает ваш умный компонент (useContext) Пора решить эту проблему раз и на всегда!

Во-первых, обозначим проблемы:

  1. Неявный DI (неясно какие сторы есть на странице и какой из десятков хуков имеет зависимость на стор).

  2. Рандомные рендеры дерева, независимо от того, слушаем мы эти пропсы или нет.

  3. Контексты, на самом деле, это лишь способ доставки пропсов, но мы же хотим построить полноценный стор?

1. withContext

Решая проблему неявного DI мы с моей командой пришли к выводу что нам требутся HOC который будет отрисовывать наши контексты/сторы последовательно. реализовывая всю нашу логику внутри стора и предоставляя доступ внутри компонента.

// Пример HOC
export const withContexts = function <T>(
  Component: React.ComponentType<T>,
  contexts: React.ComponentType[]
) {}

// Использование будет выглядеть так
export default withContexts(TodoPage, [GlobalStore.Provider])

2. connectContext

Решая проблему рандомных рендеров мы рассмотрели несколько вариантов.
Кастомный хук useStore который бы отслеживал изменения контекста глобально и событиями бы сообщал о том что значение изменилось и ререндерил бы компонент в нужный момент времени. НО мы бы так и остались с проблемой не явного DI в месте использования, что доставляло бы нам немало проблем.

Поэтому выбор пал на HOC который бы умел принимать в себя контексты и получать только ТЕ аргументы, что мы используем.

// Пример HOC
export const connectContext = function <ContextValue, ComponentProps>(
  Context: Context<ContextValue>,
  getValueByKey: (value: ContextValue) => ComponentProps
) {}

// Пример использования
export const StoreExample = connectContext(
  // Стор который используем
  // Стоит улучшить и сделать здесь больше чем 1 контекст
  GlobalStore.Context,
  // Значения сторов
  ({ state: { notifications }, actions: { updateNotifications } }) => 
  // Значения которые получит компонент 
  ({
    globalNotifications: notifications,
    updateGlobalNotifications: updateNotifications,
  })
  // Пропсы которые ожидает увидеть компонент помимо тех что получит из контекста
)<{ minDate: string }>(
  ({ globalNotifications, updateGlobalNotifications, minDate }) => {}

3. createStore

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

// Пример функции которая бы создавал стор
export const createStore = function <State, Actions>(
  // тут стоит явно расширить и научить стор слушать другие сторы,
  // планируем внедрить в ближайшее время
  useCustomHook: () => { state: State; actions?: Actions }
) {}

// Пример Создания стора
export const GlobalStore = createStore(() => {
  const [notifications, updateNotifications] = useState<string[]>([]);
  const [user] = useState({ name: "Grigoriy" });

  return { state: { notifications, user }, actions: { updateNotifications } };
});

И так в результате этих наработок я создал библиотеку и решили поделиться ею с комьюнити.

https://www.npmjs.com/package/context-base-api

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

Спасибо за внимание. Надеюсь на обратную связь.

P.S

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

Следите за обновлениями!

P.S.S

Библиотека была обновлена для использования нескольких сторов одновременно, а так же для использования зависимых сторов. Ознакомится с кодом можно на гитхабе или npmjs.

Only registered users can participate in poll. Log in, please.
А вы используете СТМ?
55.34% Redux57
14.56% Effector15
32.04% Mobx33
20.39% Context21
103 users voted. 28 users abstained.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 3: ↑2 and ↓1+1
Comments39

Articles