深入认识setState
不要直接修改state
例如,此代码不会重新渲染组件:
jsx
// bad
this.state.comment = 'Hello';而是应该使用 this.setState():
jsx
// good
this.setState({comment: 'Hello'});state的更新可能是异步的
如下列代码,我们无法在修改 state 后拿到最新的 state:
jsx
import React from 'react';
export default class MyComp extends React.Component {
state = {
x: 0
}
handleClick = () => {
this.setState({
x: this.state.x + 1
});
console.log(this.state.x);
}
render () {
console.log('render');
return (
<div>
<h1>{this.state.x}</h1>
<button onClick={this.handleClick}>+</button>
</div>
)
}
}
// 点击1次按钮后,控制台输出为:
// 0
// render要解决这个问题,可以让 this.setState() 接收第二个参数,这个参数是一个回调函数,会在 state 更新完毕并且重新渲染后执行。
jsx
import React from 'react';
export default class MyComp extends React.Component {
state = {
x: 0,
y: 0
}
handleClick = () => {
this.setState({
x: this.state.x + 1
}, () => {
console.log(this.state.x);
this.setState({
y: this.state.x * 2
});
});
}
render () {
console.log('render');
return (
<div>
<h1>{this.state.x}</h1>
<h1>{this.state.y}</h1>
<button onClick={this.handleClick}>+</button>
</div>
)
}
}
// 点击1次按钮后,控制台输出为:
// render
// 1接收一个回调函数作为this.setState的第二个参数虽然是一种解决方案,但是当我们某些数据需要依赖其他最新的数据时,回调函数会显得不那么优雅。
那么可以让 this.setState() 的第一个参数接收一个函数而不是一个对象。这个函数使用上一次更新的 state 作为第一个参数:
jsx
import React from 'react';
export default class MyComp extends React.Component {
state = {
x: 0,
y: 0
}
handleClick = () => {
this.setState(state => ({
x: state.x + 1
}));
this.setState(state => ({
y: state.x * 2
}));
}
render () {
console.log('render');
return (
<div>
<h1>{this.state.x}</h1>
<h1>{this.state.y}</h1>
<button onClick={this.handleClick}>+</button>
</div>
)
}
}state的更新会被合并
当 state 中存在多个独立的变量,并且分别被单独更新时,这些 state 的更新会被统一合并更新。
jsx
import React from 'react';
export default class MyComp extends React.Component {
state = {
foo: [],
bar: [6, 6, 6]
}
change = () => {
this.setState({
foo: this.state.foo + 1
});
this.setState({
foo: this.state.foo + 2
}, () => {
console.log(this.state)
});
}
render () {
console.log('render');
return (
<div>
<button onClick={this.change}>change</button>
</div>
)
}
}可以看到,我们在change函数中调用了两次this.setState,在更新后 state 依然保留了bar变量,并且render函数只执行了一次,这是因为 React 对this.setState做了优化,多次执行时,统一将最终的结果赋值给 state,再执行render函数。