最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Replacing new state in react redux reducer without making a copy - Stack Overflow

programmeradmin2浏览0评论

If I have pletely replacing the entirety of a slice of state, do I still have to use Object.assign or the spread operator to make a copy of the original state and replace it with the new state, or can I just return the new state in my reducer?

const fetching = (state = { isFetching: false }, action) => {
  switch (action.type) {
    case 'REQUESTING':
      return Object.assign({}, state, { isFetching: true } )
    case 'RECEIVE_POKEMON_TYPE_INFO':
      return Object.assign({}, state, { isFetching: false } )
    default:
      return state
  }
}

vs.

const fetching = (state = { isFetching: false }, action) => {
  switch (action.type) {
    case 'REQUESTING':
      return { isFetching: true }
    case 'RECEIVE_POKEMON_TYPE_INFO':
      return { isFetching: false }
    default:
      return state
  }
}

If I have pletely replacing the entirety of a slice of state, do I still have to use Object.assign or the spread operator to make a copy of the original state and replace it with the new state, or can I just return the new state in my reducer?

const fetching = (state = { isFetching: false }, action) => {
  switch (action.type) {
    case 'REQUESTING':
      return Object.assign({}, state, { isFetching: true } )
    case 'RECEIVE_POKEMON_TYPE_INFO':
      return Object.assign({}, state, { isFetching: false } )
    default:
      return state
  }
}

vs.

const fetching = (state = { isFetching: false }, action) => {
  switch (action.type) {
    case 'REQUESTING':
      return { isFetching: true }
    case 'RECEIVE_POKEMON_TYPE_INFO':
      return { isFetching: false }
    default:
      return state
  }
}
Share Improve this question asked Aug 29, 2016 at 6:55 mangocaptainmangocaptain 1,4951 gold badge20 silver badges32 bronze badges 3
  • If you can replace return Object.assign({}, state, { isFetching: true } ) with return Object.assign({}, { isFetching: true } ) , then you can replace it with { isFetching: true }. Otherwise, you cannot because rest of state will be lost. – Pandaiolo Commented Aug 29, 2016 at 16:07
  • I think there's a similar question has been answered here – Bryan Tung Commented May 8, 2017 at 18:06
  • I think there's a similar question has been answered here. – Bryan Tung Commented May 8, 2017 at 18:09
Add a ment  | 

2 Answers 2

Reset to default 6

There are a couple of things going on here. Basically, if your state only consists of a boolean variable, then creating a new object by enumeration is OK. However, if your state consists of other things, then doing an object.assign should work.

However (and isn't there always a 'however'), if your state is plex - that is it consists of other objects then doing object.assign will not properly copy the fields - it copied the references not the values. For example, if your state consists of a "currentlySelectedPokemon" field there the value is a Pokemon object, then Object.assign will copy a reference to the pokemon object. It won't copy the object itself. To show this more easily, look at the code below - it prints "value2" for obj2.

var obj1 = {
  field: {
    subfield: "value"
  }
};

var obj2 = Object.assign({}, obj1);

obj1.field.subfield = "value2";

console.log(JSON.stringify(obj2, null, 2));

There are two ways to get around this. The first is to use the Immutable library for all your state. However, I found the overhead of converting plex objects into Immutable and back provided enough plexity that it introduced unnecessary bugs. So now I do this:

const fetching = (state = { isFetching: false }, action) => {
  switch (action.type) {
    case 'REQUESTING':
      const newState = JSON.parse(JSON.stringify(state));
      newState.isFetching = true;
      return newState;
    case 'RECEIVE_POKEMON_TYPE_INFO':
      const newState = JSON.parse(JSON.stringify(state));
      newState.isFetching = false;
      return newState;
    default:
      return state
  }
}

It turns out that JSON.parse(JSON.stringify(object)) is a fast reliable way to make a copy of a vanilla java object. It strips all functions (which is what I generally want). And it's fast because browsers usually implement those functions in native code.

you can either use Object.assign or spread operator, like below

using Object.assign:

const fetching = (state = { isFetching: false }, action) => {
  switch (action.type) {
    case 'REQUESTING':
      return Object.assign({}, state, { isFetching: true } )
    case 'RECEIVE_POKEMON_TYPE_INFO':
      return Object.assign({}, state, { isFetching: false } )
    default:
      return state
  }
} 

using spread operator:

const fetching = (state = { isFetching: false }, action) => {
  switch (action.type) {
    case 'REQUESTING':
      return { ...state, isFetching: true }
    case 'RECEIVE_POKEMON_TYPE_INFO':
      return { ...state, isFetching: false }
    default:
      return state
  }
} 

using Object.assign() can quickly make simple reducers difficult to read given its rather verbose syntax.the spread (...) operator to copy enumerable properties from one object to another in a more succinct way.

发布评论

评论列表(0)

  1. 暂无评论