@dimoff66
Кратко о себе: Я есть

В чем смысл использования actions, actionCreators и т.д. в react-redux?

Общепринятый подход подразумевает, что если я хочу что-то изменить в состоянии хранилища, я должен сделать 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, а код писать уже в редюсерах.

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

Благодарю за пояснения.
  • Вопрос задан
  • 213 просмотров
Решения вопроса 1
@disappearedstar
Фронтенд-разработчик
Голый Redux — это низкоуровневый конструктор и набор рекомендаций. Любой проект, использующий редакс, рано или поздно начинает использовать самописные или сторонние (типа redux-toolkit) библиотеки-обертки над редаксом, чтобы уменьшить количество бойлерплейта и упростить себе жизнь.

Если вы понимаете и принимаете свой подход, каким бы он ни был, со всеми его плюсами и минусами, и для вас он работает — используйте на здоровье. Другим он может не подойти.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы