Как инициализировать данные по умолчанию в редукторе ES5 Redux?

Пока я не могу использовать ES6/ES2015, и я застрял с ES5 для написания редукторов Redux. Поскольку параметр состояния редуктора должен быть неизменным, даже когда он undefined, я придумал следующий шаблон:

function myState( state, action ) {
    if ( typeof state === 'undefined' ) {
        return myState( { value1: 'foo', value2: 'bar' }, action );
    }
    // actual state calculation here
}

Любые альтернативные предложения или комментарии о том, как обеспечить значение по умолчанию с помощью ES5?

Изменить: После некоторых вопросов и предложений: причина, по которой я делаю рекурсивный вызов, заключается в том, что я очень серьезно отношусь к "состоянию неизменяемости". Поэтому даже когда параметр state undefined, я не изменяю сама переменная параметра. Я слишком долго держу неизменность?

Ответ 1

Redux не заставляет вас использовать синтаксис аргументов по умолчанию. Уместно только, что когда вы даете undefined как состояние, вы возвращаете что-то еще, чтобы ваше приложение могло загрузиться с начальным деревом.

Эта функция в ES6:

function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1
  case 'DECREMENT':
    return state + 1
  default:
    return state
  }
}

Является эквивалентным этой функции в ES5:

function counter(state, action) {
  if (state === undefined) {
    state = 0
  }

  switch (action.type) {
  case 'INCREMENT':
    return state + 1
  case 'DECREMENT':
    return state + 1
  default:
    return state
  }
}

Хороший способ проверить это на запустить этот код через Babel REPL.


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

Здесь нет необходимости в рекурсивном вызове. Я думаю, что ваш вопрос может содержать некоторую путаницу в отношении различия между мутацией и назначением ссылки.

Когда вы пишете

var x = { lol: true }
x.lol = false

вы мутируете объект x. Это то, что Redux не позволяет.

Однако, когда вы пишете

var x = { lol: true }
x = { lol: false }

исходный объект остается нетронутым. x "привязка" (также известная как "переменная" ) просто начинает указывать на другой объект.

Redux не заботится, если вы измените то, что означает аргумент state. Он локален для вашей функции. Верните ли вы это или нет, изменив ссылку fine , пока вы не мутируете фактические объекты или любые объекты внутри него.

Простое изменение того, что относится к переменной, не мутирует объекты:

// good: local variable called "state" refers to a different number
state = state + 1

// good: local variable called "state" refers to a different array
state = state.concat([42])

// good: local variable called "state" refers to a different string
state = state + ", lol"

Однако, изменяя что-то внутри самого объекта или объекты, которые он связывает с, независимо от того, глубоко ли он или нет, является мутацией и не разрешен Redux:

// bad: object that local variable "state" refers to has been mutated
state.counter = state.counter + 1

// bad: object that local variable "state" refers to has been mutated
var sameObjectAsState = state
state.counter = state.counter + 1

// bad: array that local variable "state" refers to has been mutated
state.push(42)

// bad: array that local variable "state" refers to has been mutated
var sameArrayAsState = state
sameArrayAsState.push(42)

// bad: object that is linked from the object that local variable "state" refers to has been mutated
state.something.deep.counter = 42

// bad: object that is linked from the object that local variable "state" refers to has been mutated
var somethingDeep = state.something.deep
somethingDeep.counter = 42

Ответ 2

Другой вариант будет примерно таким:

var initialState = { value1: 'foo', value2: 'bar' };
function myState( state, action ) {
  state = state || initialState;
  // actual state calculation here
}