想起自己(2021年) 8 月份面试时,被面试官们问了好几个 setState 的问题,现在想想,虽然回答上问题,但是了解得不深刻。我知道 setState 被设计成“异步”是为了性能,但是涉及到源码解读我就歇菜了;我知道如何让它同步,但是遇到真实的代码情况时,却不知道如何下手。说到底,当时是准备了面经把这些概念记下来,而没有真正理解它
关岭ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联公司的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:18982081108(备注:SSL证书合作)期待与您的合作!
在认识 setState 前,我们问几个常见问题
React 的理念之一是 UI=f(data),修改 data 即驱动 UI 变化,那么怎么修改呢?React 提供了一个 API ——setState(类组件的修改方法)
官网介绍:
setState(updater, [callback])
参数一为带有形式参数的 updater 函数:
(state, props) => stateChange
// 例如
// this.setState((state, props) => {
// return {counter: state.counter + props.step};
// });
setState 的第一个参数除了接受函数外,还可以接受对象类型:
setState(stateChange[, callback])
// 例如:this.setState({count: 2})
setState 的第二个参数为可选的回调函数,它将在 setState 完成合并重新渲染组件后执行。通常,我们建议使用 componentDidUpdate 来代替此方法
setState(stateChange[, callback])
// 例如: this.setState({count: 2}, () => {console.log(this.state.count)})
stackoverflow 有人问过,也有人回答过:
setState 的特性——批处理
如果在同一周期内对多个 setState 进行处理,例如,在同一周期内多次设置商品数据,相当于:
this.setState({count: state.count + 1});
this.setState({count: state.count + 1});
this.setState({count: state.count + 1});
// ===
Object.assign(
count,
{quantity: state.quantity + 1},
{quantity: state.quantity + 1},
...
)
后调的 setState 将覆盖同一周期内先调用 setState 的值
setState 必引发更新过程,但不一定会引发 render 被执行,因为 shouldCompomentUpdate 可以返回 false
state.count = 0;
this.setState({count: state.count + 1});
this.setState({count: state.count + 1});
this.setState({count: state.count + 1});
// state.count === 1,不是 3
因为 this.setState 方法为会进行批处理,后调的 setState 会覆盖统一周期内先调用的 setState 的值,如下图所示:
state.count = 0;
this.setState({count: state.count + 2});
this.setState({count: state.count + 3});
this.setState({count: state.count + 4});
// state.count === 4
因为 setState 做的事情不仅仅只是修改了 this.state 的值,另外最重要的是它会触发 React 的更新机制,会进行diff,然后将 patch 部分更新到真实 dom 里
如果你直接 this.state.xx = oo 的话,state 的值确实会改,但是它不会驱动 React 重渲染。setState 能帮助我们更新视图,引发 shouldComponentUpdate、render 等一系列函数的调用。至于批处理,React 会将 setState 的效果放入队列中,在事件结束之后产生一次重新渲染,为的就是把 Virtual DOM 和 DOM 树操作降到最小,用于提高性能
当调用 setState 后,React 的 生命周期函数 会依次顺序执行
因为性能优化。假如每次 setState 都要更新数据,更新过程就要走五个生命周期,走完一轮生命周期再拿 render 函数的结果去做 diff 对比和更新真实 DOM,会很耗时间。所以将每次调用都放一起做一次性处理,能降低对 DOM 的操作,提高应用性能
通过第二个参数 setState(partialState, callback) 中的 callback 拿到更新后的结果
onHandleClick() {
this.setState(
{
count: this.state.count + 1,
},
() => {
console.log("点击之后的回调", this.state.count); // 最新值
}
);
}
或者可以直接给 state 传递函数来表现出同步的情况
this.setState(state => {
console.log("函数模式", state.count);
return { count: state.count + 1 };
});
首先先了解三种渲染模式
在 legacy 模式下,在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中回头再说,而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state,但是,有一个函数 batchedUpdates,这个函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步更新 this.state
像 addEventListener 绑定的原生事件、setTimeout/setInterval 会走同步,除此之外,也就是 React 控制的事件处理 setState 会异步
而 concurrent 模式都是异步,这也是未来 React 18 的默认模式
首先,我们总结下关键知识点
其次,回答一下文章开头的问题(第二第三问题在文中已经回答)
setState 是同步还是异步?
名称栏目:深入浅出SetState原理篇
当前URL:http://www.shufengxianlan.com/qtweb/news14/12914.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联