【问题标题】:Why do Redux examples pass empty object as first Object.assign() argument?为什么 Redux 示例将空对象作为第一个 Object.assign() 参数传递?
【发布时间】:2015-11-20 13:46:05
【问题描述】:

redux project的todoMVC示例中,处理todos的reducer有以下几行:

export default function todos(state = initialState, action){
    ...
    case EDIT_TODO:
      return state.map(todo =>
        todo.id === action.id ?
          Object.assign({}, todo, { text: action.text }) :
          todo
      )
}

这部分代码处理更新特定的待办事项。我的问题是,因为 state.map() 总是会返回一个新数组。那么,是否还需要这样做:

Object.assign({}, todo, { text: action.text})

可以吗:

Object.assign(todo, { text: action.text})

更新

我了解Object.assign({}, blah...)Object.assign(obj, blah...) 之间的区别。让我重新表述我的问题:

Redux 希望 reducer 返回一个新状态,而不是改变现有状态。我得到它。在我的示例中,我有一个对象数组。我想交换前两个元素的顺序。查看jsbin example here

  1. 由于Array.map 总是返回一个新数组,因此对返回数组的引用肯定是一个新数组。检查。
  2. 但是,返回数组中的元素并非全新。对前两个元素的引用是新的。但是,第三项不是。它与旧数组中的第三项相同。

所以我的问题是关于第三个元素,我应该使用:

Object.assign({}, third_element) 或简单的return the third_elment

Redux 是想要一个新数组,其中包含对其中每个对象的新引用(即使这些新对象中存储的值与旧对象相同)还是只是一个只有更新元素是新元素的新数组?

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    这就是Object.assign 工作方式的本质。它返回目标对象作为其操作的返回值。所以,在第一种语法中:

    Object.assign({}, todo, { text: action.text})
    

    您正在创建一个具有todo{ text: action.text} 可枚举属性的全新对象。

    如果你这样做:

    Object.assign(todo, { text: action.text})
    

    那么todo 本身就是目标对象,所以它会被改变,这就是Object.assign 返回的东西。

    第一种方法是通过创建一个由全新对象组成的新数组来使映射操作完全不可变。

    这是一个 jsbin,说明了我的意思。请注意,在第一个示例中,数组中的原始对象已更改,这意味着状态已发生变化。在第二种情况下,原始对象保持不变:

    https://jsbin.com/boxeserave/edit?html,js,console

    【讨论】:

    • 根据 redux 的文档,我们不应该改变状态。在第一种情况下,数组是新的,正在更新的特定项目也是新的,但是,其余的项目不是新的,对吧?看看这个:jsfiddle.net/cheng_g/8dz8t25d/2
    • 用 jsbin 编辑了我的答案,希望它更清楚。
    【解决方案2】:

    来自 Dan Abramov(Redux 的创建者)的推文:

    常见的 Redux 误解:您需要深度克隆状态。现实:如果里面的东西没有改变,保持它的引用不变!

    https://twitter.com/dan_abramov/status/688087202312491008

    【讨论】:

      【解决方案3】:

      我想补充一下 sma 的精彩回答并解释为什么需要从 Object.assign 返回一个新对象。

      按照redux 的工作方式,如果reducer 返回它在state 参数中收到的相同引用,redux 将假定状态没有改变并且不会更新视图。为了告诉 redux 你正在改变状态,你必须返回一个新的引用。这就是为什么你总是会看到一个新的空对象{} 作为reducers 中Object.assign 的第一个参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-20
        • 1970-01-01
        相关资源
        最近更新 更多