This project was bootstrapped with Create React App.
Этот проект описывает преимущества создания редьюсов из стандартного класса перед использование конструкции switch - case.
Использование класса продемонстрировано в простенькой тестовой страничке, где можно добавлять и удалять строки и отправлять данные на сервер.
Работая на большом проекте столкнулся с ситуацией, что использование конструкции switch - case внутри редьюса имеет следующие неудобства:
- Если кто-то из разработчиков забыл клонировать state, то в контроллер может уйти старое дерево(реальный случай и думаю не только у меня)
- Код выглядит неряшлево. Нет четкого разделения на отдельные блоки. Много повторяющегося кода.
- Общая область видимости для переменных
- Ключи для поиска playload меток постоянно растекаются по всему коду, встречаются и в контроллере и в представлении. И в случае если метка должна быть заменена, то это влечет некоторые трудности
- Метки постоянно приходится придумывать с учетом уникальности. Чтобы они не пересекались с другими редьюсами
С учетом все этих недочетов был разработан класс который берет на себя все рутинные обязательства, такие как:
-
автоматически клонирует ветку дерева store, защищая его от мутации. Так что разработчик получает в работу уже клонированный state и может просто выполнить в нем изменения и вернуть в store
-
вместо единой функции получается класс с набором методов, каждый метод в котором отвечает за конкретный playload назначенный ему через конфигурация.
-
Соответственно у каждого метода своя область видимости
-
Вместо использования меток в контроллер импортируется набор action creators который содержит генераторы акшинов для всех методов которые были объявлены в редьюсе
-
Все метки подписаны уникальным префиксом редьюса. Чаще всего префикс берется от имени класса редьюса так что это позволяет с одной стороны сохранять уникальность и в тоже время позволяет наследовать от этого редьюса другой, при условии что у наследника смениться префикс, то мы получим потомка который имеет тот же набор акшинов, но уже другой набор меток для playloads
// создаем новый редьюс и добавляем в него стандартный класс
import stdReduce from './stdReduce';
// создаем потомка от стандартного класса
class TEST_REDUCE extends stdReduce {
initialState = { // можно указать начальную стадию редьюса тут
text: ''
};
// уникальный префикс которым будут подписаны все **метки** для данного редьюса
prefix = 'TEST_REDUCE__';
// конфигурация акшинов для данного редьюса,
// где type это **метка** акшина
// method это обработчик который будет вызван для изменения ветки store
// saga это строка определяет какой сайд эффект должен быть применен перед вызовом метода акшина
// если параметр не указан, то назначается стандартный акшин. Про поддерживаемые саги есть описание внутри файла класса
config = () => [
{ type: 'test_action', method: this.testAction.bind(this) },
];
init = () => this.subscribeReduceOnActions(this.config());
// метод получает уже клонированное состояние и данные из вызвавшего его акшина
testAction = (clone, action) => {
// какие то действия над clone...
return clone; // Метод всегда должен возвращать измененное состояние
};
}
const TEST_REDUCEInst = new TEST_REDUCE(); // создаем экземпляр класса
TEST_REDUCEInst.init(); // генерируем акшины из конфига
//экспортируем набор акшинов для использования в контроллере
export const TestReduceInstCreators = TEST_REDUCEInst.getActionCreators();
// указывает функцию поиска акшинов как стандартную. При вызове рудьюса из combineReducers запустится
// функция checkActionForState и вернет либо измененное состояние, если playload принадлежит этому классу или вернет неизменное состояние, если это не наш playload
export default TEST_REDUCEInst.checkActionForState;
для того чтобы отправить данные в редьюс мы в контроллере импортируем сет акшин креаторов
import { TestReduceInstCreators } from '../reducers/TestReduce.js';
и далее
const mapDispatchToProps = dispatch => ({
doSoAction: (params) => dispatch(TestReduceInstCreators.test_action(params))
});
здесь TestReduceInstCreators.test_action - это метод который сгенерирует нам уже подписанный меткой playload. от нас требуется только передать в него данные которые обработает метод редьюса.
params - это объест с данными который будет передан в метод testAction как параметр action внутри редьюса
вот и все)