React中复杂状态的深度合并

Deep merge of complex state in React

本文关键字:深度 合并 状态 复杂 React      更新时间:2023-09-26

当我声明以下初始状态时:

  getInitialState: function() {
    return {
      isValid: false,
      metaData: {
        age: 12,
        content_type: 'short_url'
      }
    };
  },

和我用setState更新状态,像这样:

...
let newMetaData = {  age: 20 };
...
this.setState({
        isValid: true,
        metaData: newMetaData
      });
...

生成的this.state.metadata对象只定义了年龄。但据我所知,this.setState()将它的参数合并到现有状态。为什么它在这里不起作用,这不是应该是循环合并吗?

是否有一种方法来合并新的对象属性状态对象属性在React/ES6?

setState执行浅合并。如果元数据是平面的:

this.setState({
  metaData: Object.assign({}, this.state.metaData, newMetaData),
});

或者如果使用spread:

this.setState({
  metaData: { ...this.state.metaData, ...newMetaData },
});

如果你只需要更新一个属性,另一种方法是:

this.setState({
  metaData: {
    ...this.state.metaData,
    age: 20
  }
})

setState也可以接受一个函数,该函数接收一个state参数,您可以使用lodash merge来进行深度合并。

  setState(state => merge(state, yourPartialObjectToBeDeepMerged));

这里有一个棘手的解决方案

const [complexObject, setComplexObject] = useState({a:{b:{c:1}}})
setComplexObject((s)=>{
  s.a.b.c = 2
  return {...s}
})

它是如何工作的?

对象是引用。如果您使用s.a.b.c = 2,这将更新状态,但组件不呈现,所以dom不会改变。

然后我们需要一种方式来呈现组件。如果您使用setComplexObject(s=>s),它将不会触发渲染,因为尽管ComplexObject的内部确实发生了变化,但引用仍然指向同一个对象。

所以我们需要ES6扩展运算符来重建一个对象{...s}