Что такое redux toolkit

Redux Toolkit как средство эффективной Redux-разработки

Что такое redux toolkit. Смотреть фото Что такое redux toolkit. Смотреть картинку Что такое redux toolkit. Картинка про Что такое redux toolkit. Фото Что такое redux toolkit
В настоящее время разработка львиной доли веб-приложений, основанных на фреймворке React, ведется с использованием библиотеки Redux. Данная библиотека является самой популярной реализацией FLUX-архитектуры и, несмотря на ряд очевидных преимуществ, имеет весьма существенные недостатки, такие как:

Для устранения этих недостатков разработчики Redux представили библиотеку Redux Toolkit. Этот инструмент представляет собой набор практических решений и методов, предназначенных для упрощения разработки приложений с использованием Redux. Разработчики данной библиотеки преследовали цель упростить типичные случаи использования Redux. Данный инструмент не является универсальным решением в каждом из возможных случаев использования Redux, но позволяет упростить тот код, который требуется написать разработчику.

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

Кратко о библиотеке

Краткая информация о Redux Toolkit:

Согласно заявлению разработчиков, Redux Toolkit выполняет следующие функции:

Redux Toolkit предоставляет набор как специально разработанных, так и добавляет ряд хорошо себя зарекомендовавших инструментов, которые обычно используются совместно с Redux. Такой подход позволяет разработчику решить как и какие инструменты использовать в своем приложении. По ходу данной статьи мы будем отмечать какие заимствования использует данная библиотека. Более полную информацию и зависимостях Redux Toolkit можно получить из описания пакета @reduxjs/toolkit.

Наиболее значимыми функциями, предоставляемыми библиотекой Redux Toolkit являются:

Также, стоит отметить, что Redux Toolkit полностью интегрирован с TypeScript. Более подробную информацию об этом можно получить из раздела Usage With TypeScript официальной документации.

Применение

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

Задача

В одном из наших внутренних приложений возникла необходимость добавлять, редактировать и отображать информацию о релизах выпускаемых нами программных продуктов. Для каждого из этих действий были разработаны отдельные функции API, результаты выполнения которых и требуется добавлять в Redux store. В качестве средства управления асинхронным поведением и побочными эффектами будем использовать Thunk.

Создание хранилища

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

Если внимательно взглянуть на приведенный код, можно увидеть довольно длинную последовательность действий, которую необходимо совершить чтобы хранилище было полностью сконфигурировано. Redux Toolkit содержит инструмент, призванный упростить данную процедуру, а именно: функцию configureStore.

Функция configureStore

Данный инструмент позволяет автоматически комбинировать редьюсеры, добавить мидлвары Redux (по умолчанию включает redux-thunk), а также использовать расширение Redux DevTools. В качестве входных параметров функция configureStore принимает объект со следующими свойствами:

Для получения наиболее популярного списка мидлваров можно воспользоваться специальной функцией getDefaultMiddleware, также входящей в состав Redux Toolkit. Данная функция возвращает массив с включенными по умолчанию в библиотеку Redux Toolkit мидлварами. Перечень этих мидлваров отличается в зависимости от того, в каком режиме выполняется ваш код. В production режиме массив состоит только из одного элемента — thunk. В режиме development на момент написания статьи список пополняется следующими мидлварами:

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

Теперь перепишем участок кода, отвечающий за создание хранилища, воспользовавшись описанными выше инструментами. В результате получим следующее:

На примере данного участка кода хорошо видно, что функция configureStore решает следующие проблемы:

А также позволяет более удобно включить расширение Redux DevTools, используя функцию composeWithDevTools из пакета redux-devtools-extension. Все вышесказанное свидетельствует о том, что использование данной функции позволяет сделать код более компактным и понятным.

На этом создание и настройка хранилища завершены. Передаем его в провайдер и переходим далее.

Действия, создатели действий и редьюсер

Теперь рассмотрим возможности Redux Toolkit в части разработки действий, создателей действий и редьюсера. Первоначальный вариант кода без использования Redux Toolkit был организован в виде файлов actions.js и reducers.js. Содержимое файла actions.js выглядело следующим образом:

Содержимое файла reducers.js до использования Redux Toolkit:

Как мы можем видеть, именно здесь содержится большая часть бойлерплейта: константы типов действий, создатели действий, снова константы, но уже в коде редьюсера на написание всего этого кода приходится тратить время. Частично от этого бойлерплейта можно избавиться, если воспользоваться функциями createAction и createReducer, которые также входят в состав Redux Toolkit.

Функция createAction

В приведенном участке кода используется стандартный способ определения действия в Redux: сначала отдельно объявляется константа, определяющая тип действия, после чего — функция создателя действия этого типа. Функция createAction объединяет эти два объявления в одно. На вход она принимает тип действия и возвращает создателя действия для этого типа. Создатель действия может быть вызван либо без аргументов, либо с некоторым аргументом (полезная нагрузка), значение которого будет помещено в поле payload, созданного действия. Кроме того, создатель действия переопределяет функцию toString(), так что тип действия становится его строковым представлением.

В некоторых случаях может понадобиться написать дополнительную логику для настройки значения полезной нагрузки, например, принять несколько параметров для создателя действия, создать случайный идентификатор или получить текущую временну́ю метку. Для этого createAction принимает необязательный второй аргумент — функцию, которая будет использоваться для обновления значения полезной нагрузки. Подробнее о данном параметре можно ознакомиться в официальной документации.
Использовав функцию createAction, получим следующий код:

Функция createReducer

Теперь рассмотрим редьюсер. Как и в нашем примере, редьюсеры часто реализуются с помощью оператора switch, с одним регистром для каждого обработанного типа действия. Этот подход работает хорошо, но не лишен бойлерплейта и подвержен ошибкам. Например, легко забыть описать случай default или не установить начальное состояние. Функция createReducer упрощает создание функций редьюсера, определяя их как таблицы поиска функций для обработки каждого типа действия. Она также позволяет существенно упростить логику иммутабельного обновления, написав код в “мутабельном” стиле внутри редьюсеров.

“Мутабельный” стиль обработки событий доступен благодаря использованию библиотеки Immer. Функция обработчик может либо “мутировать” переданный state для изменения свойств, либо возвращать новый state, как при работе в иммутабельном стиле, но, благодаря Immer, реальная мутация объекта не осуществляется. Первый вариант куда проще для работы и восприятия, особенно при изменении объекта с глубокой вложенностью.

Будьте внимательны: возврат нового объекта из функции перекрывает “мутабельные” изменения. Одновременное применение обоих методов обновления состояния не сработает.

В качестве входных параметров функция createReducer принимает следующие аргументы:

Воспользовавшись методом createReducer, получим следующий код:

Как мы видим, использование функций createAction и createReducer существенно решает проблему написания лишнего кода, но проблема предварительного создания констант всё равно остается. Поэтому рассмотрим более мощный вариант, объединяющий в себе генерацию и создателей действий и редьюсера — функция createSlice.

Функция createSlice

В качестве входных параметров функция createSlice принимает объект со следующими полями:

Результатом работы функции является объект, называемый «срез», со следующими полями:

Использовав данную функцию для решения нашей задачи, получим следующий исходный код:

Теперь извлечем из созданного среза создатели действий и редьюсер.

Исходный код создателей действий, содержащих вызовы API, не изменился, за исключением способа передачи параметров при отправке действий:

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

В завершении данной статьи, хотелось бы сказать, что несмотря на то, что библиотека Redux Toolkit не вносит ничего нового в управление хранилищем, она предоставляет ряд гораздо более удобных средств для написания кода чем были до этого. Данные средства позволяют не только сделать процесс разработки более удобным, понятным и быстрым, но и более эффективным, за счет наличия в библиотеке ряда хорошо зарекомендовавших себя ранее инструментов. Мы, в Инобитек, планируем и дальше использовать данную библиотеку при разработке наших программных продуктов и следить за новыми перспективными разработками в области Web-технологий.

Спасибо за внимание. Надеемся, что наша статья окажется полезной. Более подробную информацию о библиотеке Redux Toolkit можно получить из официальной документации.

Источник

Redux Toolkit больше не нужен?

История появления

Наша компания занимается разработкой проектов для стартапов по всему миру. А для этих сумасшедших вдохновенных ребят самым важным (или один из таковых) является время. Раньше вышел на рынок — выше шансы выжить. Поэтому мы всегда стараемся сократить время разработки, не жертвуя при этом качеством, и уменьшить количество ошибок, вызванных человеческим фактором. По большей части выбираем что-то стандартное и более или менее стабильное. В данном случае ничего готового найти не удалось, поэтому засучили рукава и начали смотреть, что тут можно навелосипедить.

Что такое redux toolkit. Смотреть фото Что такое redux toolkit. Смотреть картинку Что такое redux toolkit. Картинка про Что такое redux toolkit. Фото Что такое redux toolkit

Как водится, начали с описания проблемы и получили следующее:

Пока ПМ-ы ломали головы над тем, откуда взять еще пару другую часов в сутках, нашлась пара энтузиастов, которые сгенерировали и воплотили в жизнь простую до банальности идею. Да-да, гениальные идеи, после того как придумываются, всегда кажутся простыми. А идея заключалась в следующем: просто-напросто генерировать отдельные куски кода вместо того, чтобы переписывать его вручную. Использовать сниппеты и получать на выходе простыни не хотелось, т.к. любые изменения приводили к катастрофе и повторным рефакторингам, поэтому по-быстрому запилили функцию, которая принимала на вход некие параметры и строила reducer, action и saga. Так родилась первая версия коммуникаций (@axmit/redux-communications). Название “коммуникации” родилось как-то само собой, т.к. эта библиотека связывает воедино стор, саги и компоненты. Так и пошло …

Сразу после этого наступило счастье. Ну или почти сразу. Время разработки уменьшилось примерно на 20% (как мы это посчитали — тема отдельной статьи). В первую очередь — за счет значительного сокращения количества вылезающих багов. И это не говоря о том, что разработчики стали гораздо реже допускать глупые ошибки по невнимательности.

Что такое redux toolkit. Смотреть фото Что такое redux toolkit. Смотреть картинку Что такое redux toolkit. Картинка про Что такое redux toolkit. Фото Что такое redux toolkit

Линус Торвальдс как-то сказал: «Болтовня ничего не стоит. Покажите мне код.», и я полностью с ним согласен. Не буду цитировать и переписывать доку или приводить здесь простыни кода, приведу лишь небольшой пример. Ссылки на полное описание библиотеки и песочницу с примерами также можно найти в конце статьи.

Рассмотрим типичную задачу — нам нужно создать CRUD по какой-то сущности. Возьмем для примера задачу(task). Описывать стандартный вариант считаю бесполезным, т.к. он займет много места, и все, кто сталкивался с редаксом, скорее всего примерно представляют, как это будет выглядеть. А чтобы получить коммуникацию, нужно сделать следующие вещи:

1. Описать транспорт, без этого никуда

2. Описать имя namespace

3. Создать стратегию для создания коммуникации

4. Создать коммуникацию

5. Подключить редьюсеры и саги из коммуникации, как обычно

6. После этого остается подключить стор к компоненту

7. И начать пользоваться

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

Это все, что нужно сделать, чтобы иметь полностью работоспособный CRUD. Если нужно сделать что-то более сложное — можно расширить CRUD коммуникацию или использовать BaseCommunication. В крайнем случае, под капотом это все тот же старый-добрый редакс со всеми его возможностями. Гибкость не пострадала. Транспорт вынесен в отдельный слой, и его реализация может быть какой угодно. У нас на проектах есть graphQL и простые запросы с использованием axios, и трудностей в этом плане мы не испытывали. Внимательный читатель мог заметить, что библиотека экспортирует саги, и это является одним из самых существенных ее ограничений. Если по какой-то причине вы не можете использовать саги, данная библиотека, к сожалению, вам не подходит.

Почему сейчас?

Решение написать статью пришло после прочтения этой статьи. Потыкав данный инструмент, с удивлением для себя обнаружил, что коммуникации намного проще, более лаконичны, дают более четкую структуру стора и при этом не уступают в гибкости. Посидев и поразбиравшись часок с исходниками из примера к redux-toolkit, переписал его на коммуникации. Старался вносить минимум изменений, чтобы было проще отследить разницу, хотя, на мой взгляд, структура примера очень запутана. Комментарии по коду специально оставил, чтобы проще было сравнивать как было и как стало. Обратите внимание на файлы *.communication.ts и слайсы, которые они заменяют.

Что такое redux toolkit. Смотреть фото Что такое redux toolkit. Смотреть картинку Что такое redux toolkit. Картинка про Что такое redux toolkit. Фото Что такое redux toolkit

То, что количество строк намного меньше и сам код гораздо приятнее выглядит(субъективно) не столь важно, т.к. в проде у нас бывают довольно тяжеловесные коммуникации. Тут есть одно более важное отличие. Код — декларативный. Мы просто определяем, что и откуда хотим получить и что сделать с данными, а как это сделать — нас совершенно не волнует.
Вывод — redux-toolkit стоит можно использовать для кастомизации, для всего остального есть MasterCa. @axmit/redux-communications.

Подведем итоги

Полное описание библиотеки можно найти тут, а потыкать online тут.

Полный код переписанного на коммуникации примера из доки ReduxToolkit тут, а потыкать можно тут.

Источник

Что такое redux toolkit

Redux Toolkit is our official, opinionated, batteries-included toolset for efficient Redux development. It is intended to be the standard way to write Redux logic, and we strongly recommend that you use it.

It includes several utility functions that simplify the most common Redux use cases, including store setup, defining reducers, immutable update logic, and even creating entire «slices» of state at once without writing any action creators or action types by hand. It also includes the most widely used Redux addons, like Redux Thunk for async logic and Reselect for writing selector functions, so that you can use them right away.

Installation​

Redux Toolkit is available as a package on NPM for use with a module bundler or in a Node application:

Purpose​

The Redux core library is deliberately unopinionated. It lets you decide how you want to handle everything, like store setup, what your state contains, and how you want to build your reducers.

This is good in some cases, because it gives you flexibility, but that flexibility isn’t always needed. Sometimes we just want the simplest possible way to get started, with some good default behavior out of the box. Or, maybe you’re writing a larger application and finding yourself writing some similar code, and you’d like to cut down on how much of that code you have to write by hand.

Redux Toolkit was originally created to help address three common concerns about Redux:

Why You Should Use Redux Toolkit​

Redux Toolkit makes it easier to write good Redux applications and speeds up development, by baking in our recommended best practices, providing good default behaviors, catching mistakes, and allowing you to write simpler code. Redux Toolkit is beneficial to all Redux users regardless of skill level or experience. It can be added at the start of a new project, or used as part of an incremental migration in an existing project.

Note that you are not required to use Redux Toolkit to use Redux. There are many existing applications that use other Redux wrapper libraries, or write all Redux logic «by hand», and if you still prefer to use a different approach, go ahead!

Overall, whether you’re a brand new Redux user setting up your first project, or an experienced user who wants to simplify an existing application, using Redux Toolkit will make your code better and more maintainable.

What’s Included​

Redux Toolkit includes:

Redux Toolkit also has a new RTK Query data fetching API. RTK Query is a powerful data fetching and caching tool built specifically for Redux. It is designed to simplify common cases for loading data in a web application, eliminating the need to hand-write data fetching & caching logic yourself.

Источник

Redux Vs Vuex. Часть 1

Что такое redux toolkit. Смотреть фото Что такое redux toolkit. Смотреть картинку Что такое redux toolkit. Картинка про Что такое redux toolkit. Фото Что такое redux toolkit

Доброго времени суток, друзья!

Введение

Обратите внимание: Flux-архитектура предназначена для работы с глобальным или распределенным (global, shared) состоянием, т.е. состоянием, которое используется двумя и более автономными компонентами приложения. Автономными являются компоненты, между которыми не существует отношений или связи “предок-потомок” или “родитель-ребенок”, т.е. это компоненты из разных поддеревьев дерева компонентов. Состояние, которое используется одним компонентом или передается от родительского компонента дочерним и обратно (в пределах одного поддерева), является локальным (local), оно должно храниться и управляться соответствующим компонентом. Разумеется, это не относится к корневому (root) компоненту.

Архитектура Flux (в Redux ) предполагает следующее:

Это выглядит примерно так (без учета селекторов и преобразователей):

Что такое redux toolkit. Смотреть фото Что такое redux toolkit. Смотреть картинку Что такое redux toolkit. Картинка про Что такое redux toolkit. Фото Что такое redux toolkit

Для того, чтобы это выяснить, мы создадим простое приложение — список задач — со следующим функционалом:

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

Выглядеть наше приложение будет так:

Что такое redux toolkit. Смотреть фото Что такое redux toolkit. Смотреть картинку Что такое redux toolkit. Картинка про Что такое redux toolkit. Фото Что такое redux toolkit

Если вас интересует только код, то вот ссылка на репозиторий.

Демо React-приложения можно посмотреть здесь, а Vue-приложения — здесь.

Вы готовы? Тогда вперед!

Redux Toolkit

В состав Redux Toolkit входит следующее (из того, что мы будем использовать):

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

configureStore()

Метод configureStore() принимает объект со следующими свойствами:

createSlice()

Метод createSlice() принимает объект со следующими свойствами:

createSlice() под капотом использует два других метода — createAction() и createReducer() — для создания операций и редуктора, соответственно, что позволяет использовать библиотеку immer для «мутирования» состояния, т.е. для его прямой модификации.

Рассматриваемый метод возвращает такой объект:

Одной из ключевых концепций Redux является то, что каждый частичный редуктор «владеет» определенной частью состояния, и несколько таких редукторов могут обрабатывать один и тот же тип операции. extraReducers предназначены для обработки внешних по отношению к редукторам операций, например, HTTP-запросов.

Простой пример со счетчиком:

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

createAsyncThunk()

Метод createAsyncThunk() принимает тип операции, колбэк, который должен возвращать промис и объект с настройками. Также этот метод генерирует типы операций, соответствующие жизненному циклу промиса, и возвращает преобразователь (thunk), который запускает колбэк промиса и отправляет в редуктор соответствующие операции. Для обработки этих операций используются дополнительные редукторы. Да, проще показать.

Пример получения данных пользователя по его идентификатору с изменением индикатора загрузки и обеспечением отправки только одного запроса за раз:

createEntityAdapter()

createEntityAdapter() — это адаптер сущностей, функция, генерирующая набор встроенных редукторов и селекторов для выполнения GRUD-операций с нормализованными данными.

createEntityAdapter() принимает 2 параметра:

Простой пример с книгами:

Основным содержимым адаптера сущности является набор редукторов для добавления, обновления и удаления экземпляров из объекта состояния:

Каждый из указанных методов имеет такую сигнатуру:

Расширенный пример с книгами:

createSelector()

createSelector() — это метод из библиотеки Reselect для создания селекторов на основе других селекторов. Он принимает селекторы через запятую или в виде массива и возвращает новый селектор. Этот новый селектор, в свою очередь, принимает состояние, производит выборку с помощью переданных селекторов и вычисляет конечный результат.

React Redux

React Redux — это «официальный слой для связывания пользовательского интерфейса React-приложений с Redux». Он позволяет компонентам читать данные из хранилища и отправлять операции в редуктор для обновления состояния.

Провайдер

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

Хуки

React Redux предоставляет 2 хука, позволяющих компонентам взаимодействовать с хранилищем:

Хранилище React-приложения

Создание и настройка проекта

Переходим в директорию проекта и устанавливаем необходимые зависимости:

Удаляем ненужные файлы, создаем нужные, приводя проект к такой структуре:

Подключаем bootstrap и bootstrap-icons в public/index.html :

Создаем в корневой директории файл db.json следующего содержания (наша БД):

Каждая задача имеет идентификатор, текст, индикатор выполнения и индикатор редактирования.

Добавляем в раздел scripts файла package.json команду для запуска серверов для разработки: одного для БД, другого для React :

Также в package.json необходимо добавить такую строку для перенаправления запросов (по умолчанию запросы в режиме для разработки отправляются на localhost:3000 ):

Для того, чтобы убедиться в правильной настройке проекта, можно добавить такой код в файл scr/index.jsx :

и выполнить команду:

В консоли инструментов разработчика должно появиться такое сообщение:

Проектирование хранилища

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

Состояние

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

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

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

Операции

Второй вопрос: какие операции потребуются для реализации функционала нашего приложения.

Что касается задач, то нам потребуются следующие операции:

Преобразователи

Таким образом, у нас будет 3 асинхронных операции. Для обработки их результатов нам нужны 3 дополнительных редуктора. Однако, учитывая, что мы хотим переключать индикатор загрузки при получении и сохранении задач в БД, у нас будет не 3, а 5 дополнительных редукторов:

Селекторы

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

Реализация хранилища

Импортируем необходимые инструменты:

Определяем константу для адреса сервера:

Создаем адаптер сущностей для задач:

Инициализируем начальное состояние для задач:

Создаем и экспортируем преобразователь для получения задач от сервера:

Создаем и экспортируем преобразователь для сохранения задач в БД.

Реализация этого преобразователя стала для меня интересной задачей. Я пытался свести к минимуму взаимодействие приложения с сервером и ограничиться двумя асинхронными операциями: получение задач от сервера и сохранение (текущего состояния) задач в БД. Все остальные операции выполняются синхронно и локально. С первой асинхронной операцией все просто: отправляем запрос, получаем ответ. Но в случае с сохранением задач в БД ситуация несколько сложнее по следующим причинам:

Я постарался свести количество выполняемых запросов к минимуму. Вот что у меня получилось:

Создаем и экспортируем преобразователь для задержки в 2 секунды.

Создаем часть состояния для задач:

Экспортируем операции для работы с задачами:

Определяем начальное состояние, часть состояния для фильтра и экспортируем операцию для работы с ним:

Создаем и экспортируем селекторы:

Наконец, создаем и экспортируем хранилище:

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *