在不进行复制的情况下替换反应还原剂中的新状态

时间:2016-08-29 06:55:52

标签: javascript reactjs redux react-redux

如果我已经完全替换了整个状态片段,我是否还必须使用Object.assign或spread运算符来复制原始状态并将其替换为新状态,或者我可以返回我的减速机中的新状态?

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

2 个答案:

答案 0 :(得分:4)

这里有几件事情要发生。基本上,如果您的状态包含布尔变量,那么通过枚举创建新对象就可以了。但是,如果您的状态包含其他内容,则执行object.assign应该可以正常工作。

然而(并且并不总是'然而'),如果你的状态很复杂 - 那就是它由其他对象组成然后做object.assign将无法正确复制字段 - 它复制了引用而不是值。例如,如果您的状态由“currentSelectedPokemon”字段组成,那么值是一个Pokemon对象,然后Object.assign将复制对该pokemon对象的引用。它不会复制对象本身。要更容易地显示它,请查看下面的代码 - 它为obj2打印“value2”。

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

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

obj1.field.subfield = "value2";

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

有两种方法可以解决这个问题。第一种是对所有州使用Immutable库。但是,我发现将复杂对象转换为Immutable和back的开销提供了足够的复杂性,从而引入了不必要的错误。所以现在我这样做:

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

事实证明,JSON.parse(JSON.stringify(object))是一种快速可靠的方法来制作一个vanilla java对象的副本。它剥离了所有功能(这是我通常想要的)。它很快,因为浏览器通常在本机代码中实现这些功能。

答案 1 :(得分:0)

您可以使用Object.assignspread operator,如下所示

使用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
  }
} 

使用点差运营商:

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

使用Object.assign()可以快速地使简单的reducer难以阅读,因为它相当verbose syntaxspread (...)运算符以更简洁的方式将可枚举属性从一个对象复制到另一个对象。