admin管理员组

文章数量:1201376

In the todoMVC example of the redux project, the reducer for dealing with todos have these lines:

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
      )
}

This portion of the code deals with updating a particular todo item. My question here is that since state.map() will always return a new array. Then, is it still necessary to do:

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

Can it just be:

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

UPDATE

I understand the difference between Object.assign({}, blah...) vs Object.assign(obj, blah...). Let me rephrase my question:

Redux wants reducers to return a new state instead of mutating existing state. I get it. In my example, I have an array of objects. I want to swap the order of the first two elements. Check out the jsbin example here.

  1. Since Array.map always returns a new array, the reference to the returned array is gurranteed to be a new one. Check.
  2. However, the elements within the returned array are not all new. The reference to the first two elements are new. However, the third item is not. It is the same third item as in the old array.

So my question is for the third element, should I use:

Object.assign({}, third_element) or simply return the third_elment

Does Redux want a new array with new references to each object inside it (even though the values stored within those new objects are identical to the old objects) or just a new array with only the updated elements being new?

In the todoMVC example of the redux project, the reducer for dealing with todos have these lines:

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
      )
}

This portion of the code deals with updating a particular todo item. My question here is that since state.map() will always return a new array. Then, is it still necessary to do:

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

Can it just be:

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

UPDATE

I understand the difference between Object.assign({}, blah...) vs Object.assign(obj, blah...). Let me rephrase my question:

Redux wants reducers to return a new state instead of mutating existing state. I get it. In my example, I have an array of objects. I want to swap the order of the first two elements. Check out the jsbin example here.

  1. Since Array.map always returns a new array, the reference to the returned array is gurranteed to be a new one. Check.
  2. However, the elements within the returned array are not all new. The reference to the first two elements are new. However, the third item is not. It is the same third item as in the old array.

So my question is for the third element, should I use:

Object.assign({}, third_element) or simply return the third_elment

Does Redux want a new array with new references to each object inside it (even though the values stored within those new objects are identical to the old objects) or just a new array with only the updated elements being new?

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Nov 20, 2015 at 13:46 ChengCheng 17.9k23 gold badges75 silver badges105 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 14

This is the nature of how Object.assign works. It returns the target object as the return value of its operation. So, in the first syntax:

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

you are creating a brand new object with the enumerable properties of todo and { text: action.text}.

If you do this:

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

Then todo itself is the target object, so that will be mutated and that will be what is returned from Object.assign.

The first method is making the map operation completely immutable by creating a new array of entirely new objects.

Here is a jsbin that illustrates what I mean. Note that in the first example, the original object in the array has changed, meaning state has been mutated. In the second, the original object stays the same:

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

Tweet from Dan Abramov (creator of Redux):

Common Redux misconception: you need to deeply clone the state. Reality: if something inside doesn’t change, keep its reference the same!

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

I want to add to sma's great answer and explain why a new object needs to be returned from Object.assign.

With the way redux works, if a reducer returns the same reference it received in the state parameter, redux will assume that the state hasn't changed and won't update the views. In order to tell redux that you're changing the state, you must return a new reference. That's why you'll always see a new empty object {} as the first parameter of Object.assign in reducers.

本文标签: javascriptWhy do Redux examples pass empty object as first Objectassign() argumentStack Overflow