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

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

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

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

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

2 ответа

Решение

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.


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

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

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

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

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

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

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

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

Redux не волнует, что ты изменишь state аргумент относится к. Это локально для вашей функции. Независимо от того, возвращаете ли вы его или нет, изменяете эталонное значение, если вы не изменяете фактические объекты или любые объекты внутри него.

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

// 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

Другим вариантом будет что-то вроде этого:

var initialState = { value1: 'foo', value2: 'bar' };
function myState( state, action ) {
  state = state || initialState;
  // actual state calculation here
}
Другие вопросы по тегам