1. CODE I - 点击更新state

class App extends Component {state = { val: 0 }batchUpdates = () => {this.setState({ val: this.state.val + 100 })this.setState({ val: this.state.val + 200 })this.setState({ val: this.state.val + 300 })}render() {console.log(this.state.val)return (<div onClick={this.batchUpdates}>{`Counter is ${this.state.val}`} // 1</div>)}
}

console.log(this.state.val) // 输出为300

为什么是1? setState 将更新内容放入到更新队列中, 防止频繁更新带来的render()更新,对state进行【批量更新】,所以当批量更新的时候,因为key值是一样的,所以被覆盖了, 所以就只是最后一个setState的更新

class Button extends React.Component {state = { val: 0 }batchUpdates = () => {this.setState({ val: this.state.val + 1 })this.setState({ val: this.state.val + 1 })this.setState({ val: this.state.val + 1 })}componentWillMount () {this.setState({ val: this.state.val + 1 }) // 放入队列中执行 val = 0}componentDidMount() {console.log(this.state.val) // componentWillMount执行结果 val = 1this.setState({ val: this.state.val + 1 }) // 放入队列中执行}render() {console.log('+++++++++++++', this.state.val) // componentDidMount执行结果后 首次渲染是 val = 2return (<div onClick={this.batchUpdates}>{`Counter is ${this.state.val}`} // 1</div>)}}

2. CODE II - setTimeout

componentWillMount() {// 1this.setState({ value: this.state.value + 1 })console.log('1', this.state)// 2this.setState({ value: this.state.value + 1 })console.log('2',this.state)// 3setTimeout(() => {this.setState({ value: this.state.value + 1 })console.log('3-1', this.state)this.setState({ value: this.state.value + 1 })console.log('3-2', this.state)}, 0)

componentWillMount 整体是一个触发的事件。

// 1

  • A = this.setState({ value:this.state.value +1})
  • 放入执行队列中 [A]
  • console.log('1',this.state) // 0 因为此时, setState没有执行

// 2

  • B = this.setState({ value:this.state.value +1})
  • 放入执行队列中 [A, B]
  • console.log('2',this.state) // 0 因为此时, setState没有执行

// 3 setTimeout 异步 [A, B]

// 4 [A, B] 执行, 是批量同步,因为key值相同,所以this.state.val = 1

// 5 this.setState 本身是个同步, 只是放到队列中,队列执行是模拟'异步'的。单独每个是个队列。执行是同步

      this.setState({ value: this.state.value + 1 }) // 1 + 1console.log('3-1', this.state) // 2this.setState({ value: this.state.value + 1 }) // 2 + 1console.log('3-2', this.state) // 3

console.log('3-1',this.state) // 2

console.log('3-2',this.state) // 3

3. CODE III - 原生事件机制

class App extends Component {state = { val: 0 }changeValue = () => {// 0this.setState({ val: this.state.val + 1 }) // 1console.log(this.state.val) // 输出的是更新后的值 --> 1this.setState({ val: this.state.val + 1 }) // 1 + 1 = 2console.log(this.state.val) // 输出的是更新后的值 --> 2}componentDidMount() {// 事件机制 同步document.body.addEventListener('click', this.changeValue, false)}render() {return (<div>{`Counter is: ${this.state.val}`}</div>)}
}

4. CODE 发现

  • 当在 addEventListener 原生事件 或 setTimeout 里面的 setState, 是同步更新的。
  • 但是除此之外的更新,就是 异步的批量 更新的。

为虾米??????

5. 为什么?

【setState解决问题】

批量更新, 减少state的频繁更新,从而避免重复的View刷新, render()的调用。

【异步? 同步?】

setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。

setTimeout或原生事件

没有走React的合成事件机制,机制是异步的, 但是setState本身是个同步的。

6. RECAP

你真的理解setState吗? - 掘金​juejin.im

  • 【setState同步? 异步?】: 本身是同步的(执行逻辑和代码都是同步的),因为React的合成事件机制,让其现看起来很 '异步'。为了解决频繁render(), 所以批量更新。
  • 【批量更新】: 因为key值相同,批量更新会让后面的覆盖掉前面的值,所以更新的值只会是最后一个this.setState的内容。(如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新)

引用来自下面的链接

React - setState源码分析(小白可读)​juejin.im

  • 上面图: 一个函数的事件机制, 把setState内容放到队列中,等到队列执行完,close掉该事件后,再render。
  • 下面图: 事件机制已经close了,setTimeout执行两个setState内容,每个setState都是新的单独的执行队列,所以render了两次。
  • componentDidMount 这样执行, 触发 render 两次的案例。
class Button extends React.Component {state = { val: 0 }componentWillMount () {this.setState({ val: this.state.val + 10 })}componentDidMount() {setTimeout(() => {console.log(this.state.val) // 10this.setState({ val: this.state.val + 20 }) // 触发一次renderconsole.log(this.state.val) // 30this.setState({ val: this.state.val + 30 }) // 再次 触发一次 renderconsole.log(this.state.val) // 60}, 0)}render() {/*** 1. componentWillMount, 10* 2. componentDidMount - setTimeout: 10 + 20 = 30* 3. componentDidMount - setTimeout: 30 + 30 = 60*/console.log('+++++++++++++', this.state.val) return (<div>{`Counter is ${this.state.val}`}</div>)}}

7. 最后的最后

React基础2--深入挖掘setState​www.jianshu.com

if (!batchingStrategy.isBatchingUpdates) {batchingStrategy.batchedUpdates(enqueueUpdate, component);return;}
dirtyComponents.push(component);

  • 判断: 是否属于批量更新状态?
  • YES: 是批量更新。不进行state的更新操作, 将需要更新的组件 放到 dirtyComponents数组中
  • NO: 不是批量更新。进行更新操作。

【流程】

  1. 将setState事务放入队列中
  2. 存入队列: 组件对象 和 变更state内容
  3. 队列处理: 合并队列, 是否有需要合并更新的
  4. 判断正否处于【创建或更新组件】阶段,此时暂时不处理更新事宜,放到dirtyComponents数组中,等待更新。没有组件处于【创建或更新组件】该阶段。才去执行setState。
  5. 如果不是,那就直接更新。
  6. 更新过程: TRANSACTION 事务处理组件的update。事务处理完后会调用wrapper.close()

*放在setTimeout异步函数,组件已经【创建或更新 完成】此时也不需要等了。直接就执行了。

回调函数是同步还是异步_[React] 4 - setState / 异步还是同步?相关推荐

  1. react 解决 setState 异步问题

    react 解决 setState 异步问题 参考文章: (1)react 解决 setState 异步问题 (2)https://www.cnblogs.com/crazycode2/p/97158 ...

  2. @async 没有异步_玩转javascript异步编程

    一般知道,js脚步语言的执行环境是单线程的,就是它会等一个任务完成,才会进行第二个任务,然后一直向下进行,这样的执行环境简单,但是处理不了复杂的运用,当一个请求需要非常旧的时间的时候,下一个流程就会被 ...

  3. java 异步_浅谈Java异步编程

    本文来自网易云社区. Java异步编程引言 Java的异步编程其实是一个充分利用计算机CPU资源,不想让主程序阻塞在某个长时间运行的任务上,这类耗时的任务可以是IO操作.远程调用以及高密度计算任务.如 ...

  4. java多线程同步与死锁_浅析Java多线程中的同步和死锁

    Value Engineering 1基于Java的多线程 多线程是实现并发机制的一种有效手段,它允许编程语言在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间相互独立,且与进程一样拥有独立 ...

  5. servlet异步_关于Servlet和异步Servlet

    servlet异步 Servlet API是Java EE标准的一部分,自1998年正式发布2.1规范以来,一直是基于Java的企业体系结构的重要组成部分. 它是一种自以为是的API,用于服务围绕一些 ...

  6. onenote怎么同步到电脑_详解onenote保存与同步④:本地笔记奇葩的丢失经历

    (此文介绍的是我遇到过的,极其奇葩的,丢失onenote本地笔记的惨痛经历.不论是否具有普遍性,对进一步理解缓存还是很有帮助的.大家若有其他丢失经历,可以交流.) 对于onenote本地笔记本而言,由 ...

  7. mac电脑如何与手机同步复制粘贴_苹果换安卓手机如何同步手机自带备忘录便签?...

    我的同事小李之前一直使用的是苹果手机,这次换手机的时候,他准备苹果换安卓手机使用试试,我问他准备选择哪款手机?小李告诉我自己已经看好了一款安卓手机,vivo x50这款拥有超感微云台摄影的手机让他非常 ...

  8. onenote怎么同步到电脑_详解onenote保存与同步⑤:笔记的备份

    了解onenote保存与同步机制后,接下来该谈谈笔记备份的问题了.不论你是喜欢云端还是本地笔记,备份都是重中之重,它能最大限度地确保你的笔记不丢失. 前一篇文章谈到了我个人丢失本地笔记的惨痛经历,这个 ...

  9. rsync 同步数据记录_非初学者指南与Rsync同步数据

    rsync 同步数据记录 The rsync protocol can be pretty simple to use for ordinary backup/synchronization jobs ...

  10. js同步异步 回调函数

    学js这么久 只知道它是一个单线程的语言,同步异步听了这么多从未深思过. 在写ajax请求时再一次看见回调函数,想到在网上去查查详细的知识,没想到查出一大堆讲同步异步的,看了不少人的文章,这才感觉自己 ...

最新文章

  1. 赵方庆 北京生科院Computational strategies in exploring circular RNAs 探索环状rna的计算策略
  2. Cisco防火墙技术汇总[转贴]
  3. P3758 [TJOI2017]可乐
  4. 猪的诱惑(2005-12-25 15:45:05)(新浪)
  5. KNN算法的简单实现
  6. 局部类型 之 部分方法
  7. mysql where is_MySQL中条件放在where后面与放在on后面的区别
  8. 明确职责分工的重要性_发挥属地作用明确责任分工
  9. windows server 2003 32位支持8G内存
  10. 在禁用视图状态的情况下仍然使用ViewState对象
  11. python基础--面向对象之封装
  12. Silverlight中无法设置卫星程序集为中立资源程序集
  13. ln命令 Linux软连接(Symbolic Link)和硬链接(Hard Link)
  14. 微信小程序发布后使用本地图片不显示问题
  15. 将用户需求转成产品需求
  16. java扫码枪键盘_浅谈在react中如何实现扫码枪输入
  17. vivo 5G旗舰机真的要来了?新商标好抢眼!
  18. JAVA-基础(Stream流)
  19. Axure下拉框的多选与取消
  20. java通过framer生成word_DSO Framer Control Object 操作word文件

热门文章

  1. acm常见错误-持续更新
  2. DataTemplate 以及Template Selector 学习笔记
  3. 华为OSPF多区域+路由重发布/路由引入
  4. 计算机专业外语的特点,计算机专业英语在邮政信息技术领域的应用特点|计算机专业哪个好...
  5. adb 静默安装_Android静默安装的实现方案(一)
  6. nginx相关概念——负载均衡和动静分离
  7. 关于VXLAN实验中CE设备的BUG问题
  8. 如何在本地使用markdown进行博客编辑
  9. 集成源码深度剖析:Fescar x Spring Cloud 1
  10. 页面加载速度缓慢时,如何优化?