【问题标题】:How to initialize default data in ES5 Redux reducer?如何在 ES5 Redux reducer 中初始化默认数据?
【发布时间】:2016-02-26 08:31:41
【问题描述】:

目前我不能使用 ES6/ES2015,并且我坚持使用 ES5 来编写 Redux reducer。由于 reducer 的 state 参数必须是不可变的,即使它是未定义的,我想出了以下模式:

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

关于如何使用 ES5 确保默认值的任何替代建议或 cmets?

编辑:经过一些问题和建议:我进行递归调用的原因是我非常重视“状态是不可变的”。所以即使state参数是undefined,我也不改变参数变量本身。我是否将不变性太过分了?

【问题讨论】:

  • 为什么要再次调用myState,而不是使用state={ value1: 'foo', value2: 'bar' }?这样做的预期优势/目的是什么?
  • 这将改变应该是不可变的statevariable。还是我把不变性看得太远了?
  • 取决于您从什么角度看待myState。如果它来自调用方,那么您可能需要克隆state(如果它不是undefined)以确保它不会在myState 或您将state 传递到的任何其他函数中更改。

标签: javascript redux ecmascript-5


【解决方案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
  }
}

验证这一点的好方法是run this code through the 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

【讨论】:

    【解决方案2】:

    另一种选择是这样的:

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

    【讨论】:

    • initialState 放入myState 是更好的封装选项吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多