1.setState是合并动作,不是替换动作
this.state = {name: 'dandan', age: 20}
//当使用this.setState{name: 'fufu'}时,并不会删除age属性,而是只更改name属性值
this.setState{name: 'fufu'} //{name: 'fufu', age: 20}
2.setState动作会触发render函数的执行,使其返回最新的数据
以下代码每次点击都会输出'render被调用'
import React from "react";
import ReactDOM from "react-dom";
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
num: 1,
};
this.add = this.add.bind(this);
}
render() {
console.log('render被调用');
return (
<div>
<button onClick={this.add}> 加1 </button>{" "}
</div>
);
}
add() {
let num = this.state.num;
this.setState({
num: num + 1,
});
}
}
ReactDOM.render(<Demo> </Demo>, document.getElementById("root"));
3.setState 只在合成事件(例如onclick)和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。
import React from "react";
import ReactDOM from "react-dom";
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
num: 0,
};
}
componentDidMount() {
this.setState({
num: this.state.num + 1
})
this.setState((state) => {
console.log(state.num) // 1
return {
num: state.num + 1
}
})
console.log(this.state.num) //输出0
setTimeout(() => {
this.setState({
num: this.state.num + 1
})
console.log(this.state.num) //3
}, 0);
}
render() {
return null;
}
}
render() {
return null;
}
}
ReactDOM.render(<Demo></Demo>, document.getElementById("root"));
setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。
4.setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,就像Object.assign方法一般(但是如果使用函数作为参数传递给setState的话,就不会被覆盖)。如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。
import React from "react";
import ReactDOM from "react-dom";
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {
num: 0,
};
}
componentDidMount() {
this.setState({
num: this.state.num + 1
})
this.setState({
num: this.state.num + 1
})
this.setState({
num: this.state.num + 1
})
}
render() {
//这里会输出两个结果
//第一次输出的结果为0,为初次渲染组件的时候,获取的num值
//第二次输出的结果为1.为在钩子函数里改变num状态时发生的更新,而两次更新放在了一起且对同一个属性操作,则只会执行最后的一次。
console.log(this.state.num)
return null;
}
}
ReactDOM.render(<Demo></Demo>, document.getElementById("root"));
网友评论