从上篇我们知道 state 会通过 setState、setX 创建新对象触发 UI 更新,那么对 state 当中某一个参数更新时其它参数内容会被覆盖吗?
类组件
- 当 State 里面有 n、m
class App extends React.Component {
constructor() {
super();
this.state = { // 初始化
n: 0,
m: 0
};
}
addN() {
this.setState({ n: this.state.n + 1 });
// m 会被覆盖为 undefined 吗?
}
addM() {
this.setState({ m: this.state.m + 1 });
// n 会被覆盖为 undefined 吗?
}
render() {
return (
<div className="App">
n:{this.state.n} // 读
<button onClick={() => this.add()}>+1</button>
m: {this.state.m} // 读
<button onClick={() => this.addM()}>m+1</button>
</div>
);
}
}
结果发现并不会覆盖。那真的是这样吗?
- 当 State 里面有了第二层属性 举个栗子:只修改了 name
class App extends React.Component {
constructor() {
super();
this.state = {
n: 0,
user: {
name: "chili",
age: 18
}
};
}
changeUser() {
this.setState({
user: {
name: "tom"
}
});
}
render() {
return (
<div className="App">
n:{this.state.n}
name:{this.state.user.name}
age:{this.state.user.age}
<button onClick={() => this.changeUser()}>改变 name</button>
</div>
);
}
}
结果发现只修改 name,n 未变,但是 age 置空了?如何解决?
- ... 操作符
changeUser() {
this.setState({
user: {
...this.state.user,
name: "jem"
}
});
}
- Object.assign
changeUser() {
const user = Object.assign({}, this.state.user);
user.name = "jack";
this.setState({
// m 和 n 不会被置空
user: user
});
}
函数组件
- 写法一:两个 State
function App() {
const [n, setN] = React.useState(0);
const [m, setM] = React.useState(0);
return (
<div className="App">
n:{n}
<button onClick={() => setN(n + 1)}>+1</button>
m:{m}
<button onClick={() => setM(m + 1)}>+1</button>
</div>
);
}
不会互相覆盖互不影响
- 写法二:不推荐的写法,会被影响即置空
function App() {
const [state, setState] = React.useState({
n: 0,
m: 0
});
return (
<div className="App">
n:{state.n}
<button onClick={() => setState({ n: state.n + 1 })}>n+1</button>
m:{state.m}
<button onClick={() => setState({ m: state.m + 1 })}>m+1</button>
</div>
);
}
结果发现函数组件的 setX 连第一层属性也不会合并,那么可以通过 ... 操作符解决
总结
- 类组件的 setState 会自动合并第一层属性
- 但是不会合并第二层属性
- 可以通过 Object.assign 或者 ... 操作符解决
- 函数组件的 setX 不会合并任何一层属性
- 也可通过 ... 操作符解决changeUser()