Redux — пересмотр логики reducer’a и actions

в 18:32, , рубрики: actions, javascript, ReactJS, reducers, redux

Redux — пересмотр логики reducer'a и actions - 1
На днях ковыряясь в множестве файлов redux'a, где по логике файлы вынесены в reducers, actions, константы типов actions. Bсе это оказалось весьма не простая задача держа все эти типы файлов у себя в голове и прослеживать логику. И… эврика, появилась идея упрощения написания redux логики. Возможно создавая свой велосипед, но кто не пытался писать свои велосипеды? Но главное это не написание а поддержка написанного когда. Давайте я вам немного постараюсь показать свое видение моей логики redux'a.

Начало

И так у нас есть reduce:

// импортируем константы
import { TODO } from './actions/const';
.....
// может быть ооочень много импортов 
....

// и наконец наш reducer
function todoApp(state = initialState, action) {
  switch (action.type) {
    case TODO.SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    case TODO.ADD_TODO:
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      })
    case TODO.TOGGLE_TODO:
      return Object.assign({}, state, {
        todos: state.todos.map((todo, index) => {
          if (index === action.index) {
            return Object.assign({}, todo, {
              completed: !todo.completed
            })
          }
          return todo
        })
    })
   ...
  тут тоже может быть ооч много букв и вырастает до... ну в общем только поиск тебе поможет в этом лапшевидном файле
   ...
    default:
      return state
  }
}

взят из оф доки по redux.

action имеет вида типа:

// импортируем константы
import { TODO } from './const';

export const addTodo = (value) => ({
  type:  TODO.ADD_TODO,
  payload: value
})

константы я думаю нет необходимости показывать.

БООЛЬ

Попробую описать неистовство которое я испытываю читая код особенно при дебаге или расширении функционала.

  • поиск — нужно все время нажимать Ctrl + F причем глобально Ctrl + Shift + F
  • не видно сразу от куда ноги растут. Вытекает из пункта выше.
  • нет, это всего мало, так у меня еще весь проект пронизывают константы. Нет я не против констант но зачем? Тем более если их использовать вместе с вложенностью как в примере да если еще их конкатенировать из нескольких то это вообще ад навигации.
  • логика размазана. В одном месте действия в другом обработка этих действий в третьем (опционально) константы которые нужны только тем двум.
  • мне нужно при разработке или дебаге держать открытыми много файлов. Вытекает из пункта выше.
    ну и тп.

Вступление в логику

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

reducer

подсмотрено в google

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

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

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

action

Как было сказано выше это само действие, и логика того какую энергию передать (в нашем случае данные).

И так поехали. Мой Велосипед

reducer:

export function todoApp(state = initialState, action) {
    if (typeof action.func === 'function') {
        return action.func(state);
    }
}

да это весь мой reducer. Щас возможно будет небольшой разрыв шаблонов, как? мы вынесли логику из reducer'a..? Да. скажу я вам, мы вынесли логику из reducer'a!!!

Давайте посмотрим на action:

export function addTodo = (value) => ({
    type:  'ADD_TODO' ,
    payload: value,
    func: (state) =>({...state, value})
  })
}

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

Стоит заметить Мы убрали константы. Да и switch тоже. Что позволило снизить сложность выполнения О(1) в reducer'e.

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

Автор: bad4iz

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js