Общепринятый подход подразумевает, что если я хочу что-то изменить в состоянии хранилища, я должен сделать 4 действия:
1) Создать константу для действия (посылать и обрабатывать строки естественно неудобно)
2) Создать action creator
3) В каждом компоненте создать функцию для mapDispatchToProps, которая вызывает creator
4) Прописать логику изменения состояния в редюсере
А чего все так сложно, если в подавляющем большинстве случаев(по моему опыту) это все равно один тип, один креатор и одна логика его обработки в редюсере? Почему не упростить? Например, создаем файл actions.js (Или много файлов с логической разбивкой), в котором прописываем функции, сразу же меняющие состояние
// actions.js
export const setCategories = (payload, setState, currentState) => setState({ categories: payload })
export const addCategory = (payload, setState, currentState) => setState({ categories: [...currentState.category, payload] })
и чтобы это все работало, создаем пару универсальных функций
1)
getActions, которая автоматически соберет из actions.js все экспорты для mapDispatchToProps, она может выглядеть примерно так
// actionsDispatcher.js
import * as actions from 'actions'
const getActions = (dispatch, ownProps) => {
Object.keys(actions).forEach(actionName => {
const fn = actions[actionName]
actions[actionName] = payload => dispatch({ action: fn, payload, type: _.toSnakeCase(actionName) })
}
return actions
}
То есть она пошлет в редюсер не только данные, но и саму функцию обработки. И в компонентах нам достаточно написать
const mapDispatchToProps = getActions
чтобы через props получить доступ к любому action
2)
setState которая будет работать аналогично реактовской setState, используемой в компонентах, но для состояния хранилище. Код описывать не буду, в любом случае он не сильно сложный, главное сделать спрединг состояния автоматом.
и в редюсере будет просто строчка
function rootReducer(state = initialState, action) {
if (typeof action.action === 'function') {
return action.action(action.payload, setState, state)
} else if (action.type === '...') {
// здесь обычный подход
}
}
Что категорически неправильного в подобном подходе? Абрамов писал где-то, что подобная схема будет плоха, если один action creator используется для нескольких редюсеров. Но мне не очень понятно как это? Чтобы редюсер мог обработать действие у него должен же быть свой тип? Или предполагается, что один креатор может вызываться с разным action type И по разному соответственно в разных редюсерах обрабатываться? Тогда это имеет какой-то смысл, но насколько часта такая ситуацияю И в любом случае как следует из моего кода для редюсера эту ситуацию можно обработать и в отдельных случаях писать код непосредственно в редюсере в зависимости от типа. Например это можно сделать задав в actions для этого конкретного действия не функцию а объект со свойством type, а код писать уже в редюсерах.
На мой взгляд такой подход будет значительно удобней и при этом сохранятся все преимущества и возможности общепринятого подхода.
Благодарю за пояснения.