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

man*_*ain 5 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
  }
}
Run Code Online (Sandbox Code Playgroud)

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
  }
}
Run Code Online (Sandbox Code Playgroud)

Tim*_*ght 5

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

但是(如果不是很复杂,状态就不总是这样),也就是说,它的状态是由其他对象组成的,那么执行object.assign将不会正确地复制字段-它会复制引用而不是值。例如,如果您的州由“ currentlySelectedPokemon”字段组成,则该值是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));
Run Code Online (Sandbox Code Playgroud)

有两种方法可以解决此问题。第一种是对所有状态使用不可变库。但是,我发现将复杂对象转换为不可变对象并提供足够多的复杂性以至于引入了不必要的错误的开销。所以现在我这样做:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

事实证明,JSON.parse(JSON.stringify(object))是制作香草java对象副本的一种快速可靠的方法。它剥离所有功能(这是我通常想要的)。而且速度之快是因为浏览器通常以本机代码实现这些功能。


Md.*_*med 1

您可以使用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
  }
} 
Run Code Online (Sandbox Code Playgroud)

使用扩展运算符:

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
  }
} 
Run Code Online (Sandbox Code Playgroud)

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