💾 Состояние состояния

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

🤔 Проблема


Мобильное приложение Chipper Cash очень быстро выросло и стало поддерживать ряд различных продуктов и функций, что, к сожалению, оставило наше управление состоянием в пыли, поскольку оно становится все более сложным и трудным для понимания. Как и подобает начинающим предпринимателям, мы быстро отправляли продукцию, чтобы доказать свои идеи и нашу бизнес-модель. Однако по мере того, как мы превращаемся из небольшой в большую команду инженеров, нам необходимо рассмотреть нашу текущую систему управления состоянием и паттерны, чтобы обеспечить последовательность, тестируемость и отсутствие ошибок в приложении.

Когда мы думаем о глобальных данных, мы можем разделить их на две части: данные, которые поступают из удаленных источников, таких как API, или данные, которые пользователь вводит локально, например, через форму.

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

👨🏫 История

До начала этого проекта мобильное приложение использовало MobX (версия 4) для управления состоянием, у нас был один файл хранилища, включающий более 1500+ строк кода, используемого для получения, хранения и обновления локальных и удаленных данных. Это хранилище затем используется в любом компоненте React, которому требуется доступ к данным. Мы увидели несколько любимых шаблонов — но это практически свобода для всех.

🤷♂️ Варианты


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

Mobx

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

Поскольку Mobx является «механизмом управления состоянием», подобно Context, он часто используется в паре с такими библиотеками, как MobX-State-Tree, предлагающими структуру и общие инструменты, необходимые для приложений.

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

Context

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

  • Context часто упоминается как более подходящий для нечастых обновлений, таких как темы и логика аутентификации. См. статью Дэна Tweet and Log Rockets Pitfalls of Overusing Context для более глубокого изучения этого утверждения.
  • В какой-то момент Redux использовал Context под капотом, но затем отказался от него из-за проблем с производительностью, о чем говорится в примечаниях к релизу — хотя теперь, возможно, эта проблема решена.
  • Почему React Context не является инструментом «управления состоянием» — отличное чтение, которое повторяет вышеизложенные опасения.

В целом, Context — это не совсем то, что мы искали — это инструмент. Поэтому мы чувствовали, что в итоге будем изобретать колесо, разрабатывая собственное решение для управления состояниями и паттерны поверх Context.

Redux

Redux позиционирует себя как предсказуемый контейнер состояний для Javascript-приложений, в своей основе он построен на архитектуре Flux. По этой причине существует четкий способ хранения, структурирования и обновления состояния тестируемым, неизменяемым и повторяемым способом. Однако он по-прежнему не зависит от настройки хранилища, того, что содержит ваше состояние, как вы хотите построить свои редукторы и справиться с асинхронными действиями.

  • Поскольку мы отправляем действия для обновления состояния в Redux, мы сможем легко отслеживать происходящее, легко отлаживать ошибки и воспроизводить состояние. — Примечание: аналогичный паттерн доступен с MobX-State-Tree.
  • Redux славится большим количеством шаблонов, необходимых для выполнения простых задач. В небольших приложениях это может быть обременительно, и Mobx может быть более лаконичным вариантом, однако по мере роста приложений и команд это становится все менее актуальным, особенно если учесть следующее…
  • Команда Redux недавно создала Redux Toolkit (RTK), чтобы решить проблемы, связанные с шаблонами, и обеспечить индивидуальный подход к структурированию приложений Redux. Более подробная информация на сайте Redux Toolkits.
  • Redux существует уже давно — по крайней мере, в мире Javascript. Я рекомендую прочитать «Историю React-Redux» для более детального обзора того, как Redux пришел к тому, чем он является сегодня.
  • Redux позволяет нам создавать сложные потоки и даже связывать их с другими действиями. Например, каждый раз, когда возвращается новый verificationStatus для пользователя, мы можем запустить Saga, которая проверит ряд правил перед маршрутизацией пользователя. Затем это можно протестировать с помощью библиотеки типа redux-saga-test-plan.
  • По умолчанию Redux не поддерживает асинхронные потоки. У инженера есть выбор: использовать Thunks или Sagas. TLDR: Thunks = простой, Sagas = сложный — но очень мощный. Уровень детализации в этих решениях низкий, что обеспечивает большую гибкость и опять же необходимость разработки собственных лучших практик. Sagas и Thunks — это разные инструменты, которые могут достигать как схожих, так и различных целей; однако следует рассмотреть наиболее подходящий инструмент для данной работы.
  • RTK — отличное начало для улучшения Redux, однако гибкие потоки async оставили дыру в вопросе «что является лучшей практикой для управления кодом async». Именно здесь такие инструменты, как React Query, о котором пойдет речь ниже, начали заполнять пробелы. Сообщество Redux решило эту проблему с помощью RTK-Query, которая является «простой в использовании библиотекой для получения и кэширования данных».
  • RTK-Query предоставляет сравнительную таблицу с другими решениями.
  • Загляните в Dev-блог Марка, где вы найдете потрясающие материалы — в частности, серию Idiomatic Redux.

Пример

Мы создали пример базовой выборки данных и счетчика в Redux с помощью RTK и RTK-Query. Отчасти приятной особенностью является автоматически сгенерированный и типизированный API, созданный с помощью @rtk-incubator/rtk-query-codegen-openapi, который внедряется в Redux через промежуточное ПО, позволяя нам просто вызывать:

const {data, error, isLoading} = api.useGetChargesQuery({});

в нашем компоненте без лишних шаблонов. — Очень похоже на React Query ниже, но с добавленной мощью Redux за кулисами для более сложных потоков, плюс это сохранит все наши данные в едином источнике правды.

React Query

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

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

Пример

Мы создали пример React Query, соответствующий приведенному выше примеру Redux. Автоматически сгенерированный API в этом примере был более утонченным, чем тот, который мы видели в RTK-Query, но это ожидаемо от более зрелой библиотеки.

Recoil — почетное упоминание

Recoil — это экспериментальный набор утилит для управления состояниями в React от Facebook. Посмотрите это видео для более подробной информации — это круто, но еще рано для принятия. Это демонстрирует, как управление состояниями все еще совершенствуется и разрабатывается в экосистеме React. Определенно, за этим нужно следить!

🚀 Наше будущее


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

🍦 Претенденты

Мы рассмотрели несколько различных вариантов…

  • React Query & Redux + RTK. React Query для обработки вызовов API, Redux и RTK для глобального управления состоянием.
  • Redux, RTK & RTK-Query (Query теперь является частью RTK). Это означает, что наше хранилище Redux будет единым источником истины для всех данных.

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

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

При обращении к удаленным данным с помощью вызовов API очевидно, что интерфейс и возможности, которые предлагает такая библиотека, как React Query, являются предпочтительным методом. По этой причине выбор RTK-Query показался нам отличным местом для старта, даже с учетом того, что на момент начала работы он находился в альфа-версии. Мы могли бы поискать возможность создания собственных паттернов потока async и помощников, однако использование & поддержка RTK-Query показалась нам более устойчивым долгосрочным решением.

Быстрая перемотка вперед ⏱


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

  • Redux Query — эволюционирует, чтобы стать частью RTK и выйти в производство.
  • У пользователей улучшилась производительность сети.
  • Проще поддерживать API с помощью генерации кода и типов для нашего клиента Redux Query — скоро будет пост в блоге по этому поводу.
  • Роскошь использования крючков для доступа к данным API.
  • Разделение срезов Redux на области функций, что означает, что даже управление состоянием масштабируется, чтобы избежать ошибок, возникающих в различных областях функций.
  • Намного проще поддерживать кодовую базу и состояние.
  • Кодовая база, которую мы уверенно масштабируем с большим количеством новых инженеров.

📣 Мы нанимаем сотрудников — зайдите на страницу карьеры Chipper Cash, чтобы увидеть наши текущие открытые вакансии.

Оцените статью
Procodings.ru
Добавить комментарий