Задать вопрос
@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, а код писать уже в редюсерах.

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

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

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

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

Похожие вопросы
ITK academy Нижний Новгород
от 80 000 до 120 000 ₽
ITK academy Воронеж
от 50 000 до 90 000 ₽