Shower Presentation Engine

Yours Truly, Famous Inc.

Zustand.js пришел изменить все правила игры!

Забудьте все, что вы знали о стейт-менеджерах прежде.

Вступительное слово

Сложность в программировании никуда не исчезает - она лишь перераспределяется и перетекает из одной формы в другую
© undefined

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

Идеальный стейт-менеджер: какой он?

Ретроспектива развития стейт-менеджеров

Лапша-код

А кто его не писал?

Состояние приложения хранилось во множестве глобальных переменных


Преимущества: простота

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

Понятие бизнес-логики изменения состояния отсутствует

Ретроспектива развития стейт-менеджеров

Лапша-код: объект как хранилище состояния

Состояние приложения хранится в одном объекте типа appConfig


Преимущества: состояние оформлено в одну сущность

Недостатки:

Ретроспектива развития стейт-менеджеров

MV*

Теория

Ретроспектива развития стейт-менеджеров

MV*

Состояние приложения хранится в модели


Преимущества:

Ретроспектива развития стейт-менеджеров

MV*

Реальность

Ретроспектива развития стейт-менеджеров

MV*

Состояние приложения хранится в модели

Недостатки:

Ретроспектива развития стейт-менеджеров

Flux

Однонаправленный поток данных


Создание однонаправленного контролируемого и предсказуемого потока данных: представления -> канал данных -> модели -> представления

Для того, чтобы различать данные для разных сторов (моделей) в канале - данные снабдили метаданными и назвали этот тип данных Action

Ретроспектива развития стейт-менеджеров

Flux

Однонаправленный поток данных

Ретроспектива развития стейт-менеджеров

Flux

Однонаправленный поток данных


Преимущества:

Ретроспектива развития стейт-менеджеров

Flux

Однонаправленный поток данных


Недостатки:

Ретроспектива развития стейт-менеджеров

Redux

Это - Flux с единым стором и логикой по его обновлению


Изменения:

весь зопарк сторов с их не прозрачной логикой обновления заменили единым стором (полная аналогия с БД) и централизованной чистой логикой его изменения.

Добавили middleware для обработки бизнес-логики и сайд-эффектов

Ретроспектива развития стейт-менеджеров

Redux

Это - Flux с единым стором и логикой по его обновлению

Ретроспектива развития стейт-менеджеров

Redux

Это -Flux с единым стором и логикой по его обновлению


Преимущества:

Ретроспектива развития стейт-менеджеров

Redux

Это -Flux с единым стором и логикой по его обновлению

Недостатки:

Ретроспектива развития стейт-менеджеров

Итоги развития


Чего удалось достичь:

Ретроспектива развития стейт-менеджеров

Итоги развития


Чего не удалось достичь:

Zustand.js 🚀

Нирвана простота масштабируемость производительность лафа для разработчика!

Zustand.js

Давайте знакомиться


Небольшое, быстрое и масштабируемое решение для управления состоянием, основанное на принципах Flux и immutable state (как и React).

В его основе лежит хранилище основанное на базе publish/subscribe.

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

Не имеет проблем с Zombie children и context loss и отлично работает с React concurrency mode

Zustand.js

Воздушный

Zustand.js

Простой в настройке и использовании

      const storeHook = create((set, get) => { store_config })
      storeHook: (selector) => selectedState
      selector: (state) => ({ извлечённые данные из state })

      
Хук имеет статические методы: storeHook.getState: () => state storeHook.setState: (newState) => void storeHook.subscribe: (callback) => void

Zustand.js

Хранилище очень легко создавать

Zustand.js

Можно создавать сколько угодно хранилищ

Zustand.js

В хранилище можно использовать асинхронные методы

Zustand.js

Хранилище очень легко использовать в компонентах

Zustand.js

Вы можете делать даже так! Но лучше так не делать 😊

Zustand.js

Middlewares


Как и в Redux вы можете написать для хранилища свои middleware, которые будут обрабатывать события и изменять состояние хранилища.


Zustand предлагает в пакете такие middleware как:

Zustand.js

А что под капотом? Куда уж проще!?

Zustand.js

Реальная реализация хука

Zustand.js

Хранилище можно использовать везде и с любым типом кода!

Используя статические методы хука:

  • .getState()
  • .setState()
  • .subscribe()

вы получаете доступ к стору из любого окружения: как из методов стора, обработчиков событий React компонент, так и из vanilla JavaScript.

При этом вы свободно можете использовать асинхронную обработку данных и любые сайд-эффекты!💥💥💥

Zustand.js

Методы оптимизации производительности


Всего 4 простых метода:

Zustand.js

Оптимизация: вынос селектора за пределы компонента

Zustand.js

Оптимизация: оберните в useCallback селектор с параметрами

Zustand.js

Оптимизация: оберните в useShallow селектор возвращающий каждый раз новый объект

Zustand.js

Оптимизация: самый тяжелый случай

Если даже с параметрами ваш селектор может возвращать новый объект - оберните селектор в 2 хука: useCallback и useShallow

Zustand.js

Производительность на максималках

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

Итого: Zustand - мечта разработчика!

Zustand.js

Немного размышлений

Не каждый (если никто), чей голос громче всех звучит, или кто у всех на виду или в авторитете - есть Моисей!
© typeof Object

Фронтенду пришлось 10 лет бродить по технологическим дебрям, чтобы прийти к тому, к чему мы пришли сегодня с Zustand!

Pub/sub был в MV* с незапамятных времен - нам оставалось лишь выделить в абстракцию селектор, объединить все модели в один стор и оформить аналог хука!
Но на том повороте мы свернули не туда и пошли не за теми ...

Рекомендации

1. Все связанные сущности держите в одном хранилище

В последнее время у новичков, кто руками не проходил стадию развития с использованием MV*, наблюдается тенденция наступать на те грабли, что индустрия уже давно прошла: model hell - появляются различные амёбные, молекулярные, атомные и кварковые "стейт-менеджеры"

Использование отдельных хранилищь оправдано лишь:

* - когда реально нет пересечений запросов к этим сущностям

Рекомендации

2. Методы хранилища создавайте вне его описания

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

Рекомендации

3. Доступ к данным в хранилище только при помощи его методов!

Если хотите иметь надежное приложение с минимумом багов - никогда!, никогда не давайте доступ к хранилищу разрабочкикам в обход его методов!

Рекомендации

4. Создавайте настоящее хранилище данных, а не иммитацию его!

Проблема подавляющего большинства проектов заключается в том, что никто не соблюдает правило единственной отвественности - логика валидации и изменения данных размазана по всему коду, а хранилище используется исключительно как хранилище json! Отсюда и 99% багов в приложении.

Хранилище должно валидировать данные на входе, сериализивать их, проверить ссылочную целостность внутри и только после этого обновлять их и отдать их обратно сериализированными - только в этом случае вы получите не убиваемое ядро приложения и надежное приложение!

Инкапсуляция бизнес-логики в методах стора позволит безболезненно менять стейт-менеджер - приложение использует только методы сторов!

Опыт внедрения и эксплуатации

Внедрение

Перевод проекта с Redux на Zustand произошел очень быстро и без проблем - благодаря сходству семантики в обоих подходах (отправка actions/вызов методов хранилища и использование хуков) при переходе не возникало никаких проблем.

Параллельно хранилищу Redux было создано хранилище Zustand и постепенно все сущности без боли переносились в новый стор.

Самое главное - разработчики делали это с большим удовольствием и даже не просили денег за это! 😊

Опыт внедрения и эксплуатации

Эксплуатация

Сказать о том, что разработка с Zustand упростилась - это не сказать ничего!

Благодаря Zustand вся логика, связанная с доменными сущностями была собрана в хранилище. Используя Zustand вместе с "прагматичной архитектурой" (тема отдельного доклада) мы почти избавились от тестов (мы пишем их по минимуму) - в коде практически не осталось места для багов!

Мы отдали на откуп джуниоров создание визуала - они создают компоненты, логику отображения и сражаются со storybook - данные же подключаются к компонентам одной строчкой в контейнерах!
Код проекта стал структурированным, простым и понимаемым, а в проекте мы практически избавились от багов!

Ну вот и всё - финал!

Заключение


Начинайте активно в своих проектах переходить на самый простой, самый современный и самый быстрый стейт-менеджер - он существует уже несколько лет! Сделайте себе и людям хорошо!

Используйте Zustand совместно с правильной архитектурой приложения и будет вам счастье!


Желаю всем приятной и эффективной разработки!