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

Использование RTK Query вместе с Redux Toolkit [На примере Next.js + TypeScript]

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

Введение

Всем привет :) Хотел бы рассказать об использовании RTK Query + Redux Toolkit в больших проектах, а также ускорить вашу разработку и добавление новых страничек путем избавления от ненужных дублирований кода.

Если ты frontend-разработчик на react, то, думаю, тебе не впервой сталкиваться с использованием RTK Query вместе с Redux Toolkit. Но даже если это не так, то мне есть что тебе показать ;) А если ты ни разу не сталкивался с этой связкой, то, возможно, после этой статьи задумаешься о её использовании.

Предисловие

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

Установка зависимостей: yarn install. Запуск по команде: yarn dev.

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

  • Необходимо постоянно писать лоадеры, которые бы показывали загрузку страницы, а затем отрисовывали бы полученные данные.

  • Иногда хочется получить просто данные из запроса без создания отдельного слайса для страницы, а когда-то наоборот.

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

  • Если необходимы 2 и более запроса, то приходится отдельно прописывать логику и объединять запросы. А если один из них провалится, прописывать логику повторного запроса.

  • При добавлении данных в слайс в методе onQueryStarted, данные просто не успевают попасть в хранилище до отрисовки компонента, который его использует.

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

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

Структура проекта

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

Папка Redux
Папка Redux

Полезные для использование хуки и компоненты высшего порядка кладем в соответствующие папки hooks и hoc.

Папки hooks и hoc
Папки hooks и hoc

Страницы в Next.js находятся в особенной папке pages. Все примеры использования в cat-facts/index.tsx

Папка pages
Папка pages

Проблема и решение

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

Переопределяем baseQuery и принимаем через аргументы метод onSuccess, который позволит нам помещать данные в хранилище, а после этого завершать загрузку. Не забываем вызов обернуть в try catch, чтобы видеть ошибки в консоли.

Код

Пример использования слайсов и апи методов
Слайс
Слайс
Api
Api

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

Создаем специальный «хок», который будет делать запросы и выводить сообщения в случае ошибки. Логика его достаточно сложна, поэтому обратитесь к коду проекта. Находится в одноименной папке src/hoc. Можете адаптировать его под свою архитектуру проекта.

Для тех кто разбирается в TS

Типизация при использовании работает отлично, однако от костыля при преобразовании к any, я так и не смог избавиться. Если кто-то знает, как решить, прошу Merge Request в репозиторий кинуть.

Костыль
Костыль

Папка hoc
Папка hoc

Если необходимы 2 и более запроса, то приходится отдельно прописывать логику и объединять запросы. А если один из них провалится, прописывать логику повторного запроса.

Прежде чем использовать метод, создаем страничку, которая будет отрисовывать данные. Чтобы использовать данные от запросов, объединяем типы наших резолверов и наследуемся от них.

Страница отрисовки данных
Страница отрисовки данных

Далее используем «хоки» для обработки запросов к api:

Использовать «хоков»
Использовать «хоков»

withQueryResolver – содержит в себе самый главный запрос, который потом можно принять через аргументы и использовать данные. Вызывать можно только 1 раз и перед withOtherQueryResolver

withOtherQueryResolver – содержит в себе второстепенный запрос, которые нельзя принять через аргументы. Обычно используется, чтобы какие-то дополнительные данные положить в хранилище (слайсы). Должен идти после withQueryResolver. Могут быть вызваны друг за другом несколько раз. При ошибке перезагрузка данных будет только у тех, что завершились ошибкой, а не у всех сразу.

withMutationResolver – отвечает за обработку мутации, показа модалки загруузки, вывод модалки с ошибкой (если нужно). Можно адаптировать под свой проект.

Как мы видим процесс загрузки и объединения запросов занимает всего 2 строчки, а подключение логики с обработкой мутации всего 1 строчку.

И наконец прописываем страницу, которая будет экспортироваться во внешку:

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

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

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

Метод showRetryModal используем, если хотим при ошибке показать модалку, что запрос не прошел и предложить повторить запрос.

Итог

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

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

  • В случае изменения какого-то api метода, «хоки» начнут ругаться, что им передали контроллер, который принимает совсем другие данные, нежели те, что api-хук, а значит вероятность выпустить релиз с багами уменьшается в разы, ведь в production такое не скомпилируется.

  • Благодаря объединению аргументов их можно использовать как в компоненте приемнике, так и в других методах api. Например, миграция одного аргумента метода к другому методу — дело 3 секунд. Добавление какого-то нового аргумента тоже менее болезненна, ведь если он передается для какого-то другого api метода, правки не нужны и typescript не будет ругаться.

  • Если нам достаточно данных из хука, мы можем не создавать отдельный слайс под данные и, соответственно, не писать лишнего кода. Например, если наша страница всего лишь отображает данные, зачем писать для этого отдельный слайс? Можно просто взять готовые данные и отобразить.

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

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
Всего голосов 3: ↑3 и ↓0+3
Комментарии3

Публикации

Работа

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