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

В этой статье я покажу вам, как вы можете очистить свой код Redux и сделать все красиво и просто.

Создатели действий

Действия в Redux, как правило, являются эпицентром вашего спагетти-кода. Большинство новичков, включая меня, когда я впервые изучал его, не отделяли вызовы API от создателей действий. Выставка:

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

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

Типы действий

Это намного проще, чем предыдущее, и, черт возьми, вы должны делать это независимо от того, читали вы эту статью или нет! Но мы все равно расскажем об этом (на всякий случай, если вы этого не сделаете 😒).

В Redux ваше состояние обновляется в зависимости от типа действия, которое вы предоставляете. Логика обычно обрабатывается вашим редуктором. Если я хочу обновить свой список приемов пищи, я бы вызвал создателя действия с именем fetchMeal(). Вот Экспонат B:

Заметили проблему? Если вы посмотрите на строки 4 и 12, вы заметите, что это строковый литерал, а не константная переменная. Когда вы отправляете fetchMeal создателя действия, я передаю объект под названием «действие» всем своим редюсерам, который содержит свойство типа и любые другие свойства, которые вы добавляете. Затем ваши редукторы будут выполнять оператор if (или оператор switch, вы должны использовать его) и проверять, каким может быть значение «action.type». Крайне важно, чтобы тип действия, который вы передали, совпадал с действиями, которые вы пытаетесь проверить в редюсере. Например:

if ('fetch_meals' === 'fetch_meals'){
  //do something
}

Это будет означать, что блок кода внутри оператора if будет выполняться, если условие истинно. Основные вещи, верно? Тогда не о чем беспокоиться. Если только ваша кодовая база не начнет расширяться, и вам придется иметь дело с множеством создателей действий и соответствующих редюсеров. Обычно такое написание ваших действий и редукторов определенно усложняет отладку. Ваш код может быть в порядке и работать, но редьюсер не распознает тип действия, который вы передаете, если есть небольшая опечатка. Вы просто получите то же состояние, что и раньше, поскольку ваш редьюсер по умолчанию вернет текущее состояние, когда никакие условия не выполняются.

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

Теперь вы можете импортировать эти константы в свой файл действий, а также в ваши редукторы.

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

Начальное состояние

Если вы не знаете, что это такое, начальное состояние — это начальные данные, которые ваше приложение Redux будет отображать при первом запуске приложения. При первом проектировании и разработке приложения необходимо учитывать структуру ваших данных. Это поможет определить способы разделения ваших данных, а также то, как они обновляются.

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

С самого начала мы видим, что нашему приложению потребуется три редуктора. «currentFilter», «фильтр» и «еда». Когда вы создаете свои редукторы и объединяете их все вместе с помощью метода «combineReducers», ваше состояние будет выглядеть примерно так, как показано выше. Вы, вероятно, определили пару редюсеров и объединили их вместе, и вот как это будет выглядеть. Свойства верхнего уровня объекта состояния — это имена ваших редукторов. Все свойства под ними (или значения, в зависимости от того, как вы настроили некоторые из ваших редукторов) являются собственным состоянием редуктора. Всякий раз, когда вы хотите обновить определенные части своего приложения, вы отправляете определенное действие, которое поймут только определенные редьюсеры, и только эти редьюсеры будут обновлены. Это избавит от необходимости обновлять все дерево состояний.

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

Где вы должны определить свое начальное состояние? Есть два способа определить начальное состояние: либо на каждом редюсере, либо вы передаете все дерево состояний, как показано выше, в метод createStore.

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

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

Почетные упоминания

  1. Используйте операторы переключения

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

2. Используйте «bindActionCreators»

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

3. Отделите настройку редукции от вашего index.js

В большом приложении вы можете быть вынуждены добавить много промежуточного программного обеспечения и других конфигураций в свой Redux. Ваш входной файл (index.js) в конечном итоге будет загроможден таким количеством объектов конфигурации и импортированных библиотек. Итак, чтобы все было аккуратно, вы можете создать отдельный файл только для импорта библиотек и объектов конфигурации и вернуть объект хранилища. Вы можете посмотреть пример того, как это делается здесь.

Резюме

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

Надеюсь, я научил вас чему-то полезному в этой статье. Поначалу Redux может быть пугающим со всеми различными частями, которые вам нужно понять, чтобы заставить работать Redux-приложение, и я тоже боролся за хорошие 4 месяца, создавая с его помощью приложения React Native. Но, эй, со временем вы освоитесь, в конце концов, я сижу здесь и пишу эту статью, не так ли?

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