首先引入一个栗子
class Example extends React.Component {
constructor() {
super();
this.state = {
val: 0
};
}
componentDidMount() {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 1 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 2 次 log
setTimeout(() => {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 3 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 4 次 log
}, 0);
}
render() {
return null;
}
};
4次log的值 分别为 0 0 2 3
image
说一下批量更新
image
要知道setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。 如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。
在一些mv*框架中,,就是将一段时间内对model的修改批量更新到view的机制。比如那前端比较火的React、vue(nextTick机制,视图的更新以及实现)为例。
vue的nextTick机制 https://www.cnblogs.com/hity-tt/p/6729118.html
html5新特性变动观察器 http://www.cnblogs.com/jscode/p/3600060.html
消息进程 http://www.ruanyifeng.com/blog/2013/10/event_loop.html
传入回调函数
setState({
index: 1
}}, function(){
console.log(this.state.index);
})
在钩子函数中体现
componentDidUpdate(){
console.log(this.state.index);
}
在setState的第一个参数中传入function,该function会被压入调用栈中,在state真正改变后,按顺序回调栈里面的function。该function的第一个参数为上一次更新后的state。这样就能确保你下一次的操作拿到的是你预期的值
lass Com extends React.Component{
constructor(props){
super(props);
this.state = {
index: 0
}
this.add = this.add.bind(this);
}
add(){
this.setState(prevState => {
return {index: prevState.index + 1};
});
this.setState(prevState => {
return {index: prevState.index + 1};
});
}
}