在没有第三方库的情况下克隆React中的嵌套状态属性



目前我正在react中玩一些用户编辑器。当然,我遇到了反应原理:"永远不要突变。直接状态">

假设下面是一个简单用户编辑器的片段(没有显示的内容:用户对象将在按钮Save click上以json形式推送到web服务(:

import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.state = {
user: {
name: 'me',
parents: {
mother: 'mary',
father: 'john',
},
hobbies: [
{
name: 'soccer',
location: 'home'
},
{
name: 'tennis',
location: 'home'
}
]
}
};
}
onChange(e) {
let user = this.state.user; // 1 - no copy - reference
//let user = {...this.state.user}; // 2 - shallow copy
//let user = JSON.parse(JSON.stringify(this.state.user)); // 3 - deep copy
switch (e.target.dataset.ptype) {
case 'me':
user.name = e.target.value;
break;
case 'mother':
user.parents.mother = e.target.value;
break;
case 'father':
user.parents.father = e.target.value;
break;
case 'hobby':
user.hobbies[1].name = e.target.value;
break;
default:
break;
}
this.setState({
user: user
});
}
render() {
return (
<div>
<div><input data-ptype='me' onChange={this.onChange} value={this.state.user.name}/>{this.state.user.name}</div>
<div><input data-ptype='mother' onChange={this.onChange} value={this.state.user.parents.mother}/>{this.state.user.parents.mother}</div>
<div><input data-ptype='father' onChange={this.onChange} value={this.state.user.parents.father}/>{this.state.user.parents.father}</div>
<div><input data-ptype='hobby' onChange={this.onChange} value={this.state.user.hobbies[1].name}/>{this.state.user.hobbies[1].name}</div>
<div><pre>{JSON.stringify(this.state.user, null, 2)}</pre></div>
</div>
)
}
}
export default App;

在onChange方法中,我尝试了三种不同的方法来更新当前用户对象:

  1. 参考
  2. 排列运算符
  3. JSON.stringify

每种方法都能按预期工作。

这种不同方法的缺点是什么?

当然,如果我只通过引用更新用户对象,那么setState的空调用也会反映这些更改。

有关于setState如何处理/评估更新状态对象以进行渲染的概述吗?

br,Susi

处理嵌套状态并不是一种理想的方法,要么你有一个通用函数来处理对象的所有更新,要么你写了很多单独的函数来处理每个值应该如何更新。每个人都有自己的优点和缺点。

您的问题询问如何最好地克隆对象。这实际上是一个单独的问题(在这里回答(,但我建议您使用以下对象扩展语法:

const user = {
name: 'me',
parents: {
mother: 'mary',
father: 'john',
},
hobbies: [{
name: 'soccer',
location: 'home'
},
{
name: 'tennis',
location: 'home'
}
]
};
const addUserHobby = (user, newHobby) => ({
...user,
hobbies: [
...user.hobbies,
newHobby 
]
})
const updatedUser = addUserHobby(user, {
name: 'hockey',
location: 'home'
})
console.dir(updatedUser)

最新更新