这里有一个黑盒, 协调中心怎么运行的, 这是以后需要研究的了, 目前尚不清楚, 可以猜测这里边应该有个setTimeout 或者类似setTimeout的东西.
理解setState的同步单个更新下边是同步更新的示意图
这里还是结合一段代码来分析
import React from 'react'; export default class SetState extends React.Component { constructor(props) { super(props); } state = { count: 0 } click = () => { setTimeout(() => { this.setState({ count: this.state.count + 1, }) console.log('count1', this.state.count); this.setState({ count: this.state.count + 1, }); console.log('count2', this.state.count); }, 0); } render() { return ( <div onClick={this.click}> count的值{this.state.count} </div> ) } }首先遇到第一个setState, 判断是setState, 创建一个更新任务到更新队列, 然后进入协调中心, 协调中心通过某种手段判断出需要同步更新, 直接执行更新队列的任务, 得到新的state, 然后更新视图, 继续执行Main Process中的代码.
遇到console, 直接执行, 取出state(注意是更新了的)答应.
然后又遇到setState(注意这里拿到的state是更新了的), 创建更新任务进入更新队列, 然后进入协调中心, 协调中心通过某种手段判断出需要同步更新, 直接执行更新队列的任务, 得到新的state, 然后更新视图, 继续执行Main Process中的代码.
再次遇到console, 直接执行, 取出state(注意是二次了的)答应.
从以上分析可以看出同步setState为什么是同步的, 原因就在于他没有一个异步判断过程, 直接更新了state.
几点待解决的问题协调中心是什么时候, 如何判断出需要更新的
协调中心是如何识别是一个setState是在setTimeout还是在合成事件亦或生命周期等过程中的.
彩蛋说一下阅读react源码的感受, 最开始直接看src目录, react部分还行, 比较容易.
但是到了react-dom就不行了, 各种调用, 各种乱七八糟的东西, 有时跟着函数调用跳来跳去, 结果最开始想干嘛的都忘了, 这样读起来真的很打击人.
其实读源码更多不是了解其代码组织方法, 而是了解核心原理.
下边是几个小建议:
带着问题读源码, 尤其是开始读的时候, 如果漫无目的的读, 会很没有成就感, 甚至是强烈的挫败感, 读了半天也不知道学到了什么
react-dom 的src代码组织十分复杂, 建议直接读开发版的编译产物, 都在一个文件里, 比较容易找.
多用断点, 可以直接在开发版编译产物打断点看, 非常方便
不要纠结太多细节, 要抱有不求甚解的态度, 不懂的地方可以暂时放过
小结setState是一个容易让人困惑的东西, 尤其对react初学者来说, 可能感觉有点琢磨不透. 本文结合源码和自己的理解对setState的同步异步机制做了一些分析. 有些地方可能并不是十分准确, 但希望能帮助对setState同步异步机制困惑的朋友理解一些其中的原理. 最后需要记忆一下什么场景是同步更新, 什么场景是异步更新, 这个是写代码能实实在在用的到的.