1.为什么不要直接对state进行赋值?
如果直接对this.state复制是不会去更新视图的,this.setState的原理是同一个队列来实现state的更新的,将需要更新的state放入到状态队列中,在一定时间段之后,合并并更新state,然后进行渲染.而直接对this.state赋值是不会有这些操作的,因此不要对state进行直接赋值.
2.this.setState为什么是异步的?
this.setState的操作是异步的,是为了提升性能对state的更新进行批量操作,官方文档中的原话:
将
setState()
视为请求而不是立即更新组件的命令。为了更好的感知性能,React 会延迟调用它,然后通过一次传递更新多个组件。React 并不会保证 state 的变更会立即生效。
如果每一次的调用this.setState都去更新state和渲染组件,这对浏览器来说是一个很大开销。因此就需要这种批量操作以达到性能的提升。
3.如果this.setState是异步的,那么在使用当前状态去更新下个状态的时候,由于当前的state可能不是最新的,就会出现问题;那怎么解决?
class Welcome2 extends React.Component{
constructor(props) {
super(props);
this.state={a:1};
}
componentDidMount() {
console.log(this.state);//a:1
this.setState({a:this.state.a+1});
console.log(this.state);//a:1
this.setState({b:this.state.a});
console.log(this.state);//a:1
}
render() {
return <h1>{this.state.a}</h1>
}
}
this.setState的第一个参数是可以接受一个函数的,在这个函数中第一个参数是state,第二个参数是props,其中state一定是最新的。
class Welcome2 extends React.Component{
constructor(props) {
super(props);
this.state={a:1};
}
componentDidMount() {
console.log(this.state,"a");//a:1 a
this.setState((state)=>({
a:state.a+1
}));
console.log(this.state,"b");//a:1 b
this.setState((state)=>{
console.log(this.state,state);//a:1 a:2
return {b:state.a}
});
console.log(this.state,"c");//a:1 c
}
render() {
return <h1>{this.state.a} and {this.state.b}</h1>;//最终b也会被渲染到页面上
}
}
4.在批量更新时,React 总会按照定义顺序进行浅合并。
this.setState({ a: 1 });
this.setState({ b: 2 });
this.setState({ c: 3, a: 'a' });
//最终结果: a:a b:2 c:3
看一下的代码最终输入多少?
class Welcome3 extends React.Component{
constructor(props) {
super(props);
this.state={
a:1,
count:0
};
}
componentDidMount() {
const incrementChange = state => ({ count: state.count + 1 })
this.setState(incrementChange) //1
this.setState(incrementChange) //2
this.setState({ count: this.state.count + 1 }) //3
this.setState(incrementChange) //4
}
render() {
return <h1>{this.state.count}</h1>
}
}
最终在页面渲染的是2。由于第一步和第二部采用传入的函数的方式进行更新状态,所以在第二步之后count 的值就是2,在第三步中,由于并没有渲染,因此当前this.state.count是0,在进行浅合并之后,第三步执行完之后,count的值为1,第四步中就是将count赋值成1+1为2,因此输出是2。由此我们可以知道,无论第三步前执行了多少次setState,在第三步赋值的时候this.state.count都是0,浅合并之后count的值都会是1,输出的结果也都是2。