深入react源码看setState究竟做了什么?

前言

在深究 React 的 setState 原理的时候,我们先要考虑一个问题:setState 是异步的吗?
首先以 class component 为例,请看下述代码(demo-0)

class App extends React.Component {
   
  state = {
   
    count: 0
  }

  handleCountClick = () => {
   
    this.setState({
   
      count: this.state.count + 1
    });
    console.log(this.state.count);
  }

  render() {
   
    return (
      <div className='app-box'>
        <div onClick={
   this.handleCountClick}>the count is {
   this.state.count}</div>
      </div>
    )
  }
}
ReactDOM.render(
    <App />,
  document.getElementById('container')
);

count初始值为 0,当我们触发handleCountClick事件的时候,执行了count + 1操作,并打印了count,此时打印出的count是多少呢?答案不是 1 而是 0

类似的 function component 与 class component 原理一致。现在我们以 function component 为例,请看下述代码 (demo-1)

const App = function () {
   
  const [count, setCount] = React.useState(0);
  const handleCountClick = () => {
   
      setCount((count) => {
   
          return count + 1;
      });
      console.log(count);
  }

  return <div className='app-box'>
    <div onClick={
   handleCountClick}>the count is {
   count}</div>
  </div>
}
ReactDOM.render(
    <App />,
  document.getElementById('container')
);

同样的,这里打印出的 count 也为 0

相信大家都知道这个看起来是异步的现象,但他真的是异步的吗?

为什么 setState 看起来是『异步』的?

首先得思考一个问题:如何判断这个函数是否为异步?

最直接的,我们写一个 setTimeout,打个 debugger 试试看

image.png

我们都知道 setTimeout 里的回调函数是异步的,也正如上图所示,chrome 会给 setTimeout 打上一个 async 的标签。

接下来我们 debugger setState 看看

image.png

React.useState 返回的第二个参数实际就是这个 dispatchSetState函数(下文细说)。但正如上图所示,这个函数并没有 async 标签,所以 setState 并不是异步的。

那么抛开这些概念来看,上文中 demo-1 的类似异步的现象是怎么发生的呢?

简单的来说,其步骤如下所示。基于此,我们接下来更深入的看看 React 在这个过程中做了什么

image.png

从 first paint 开始

first paint 就是『首次渲染』,为突出显示,就用英文代替。

  • 这里先简单看一下App往下的 fiber tree 结构。每个 fiber node 还有一个return指向其 parent fiber node,这里就不细说了

我们都知道 React 渲染的时候,得遍历一遍 fiber tree,当走到 App 这个 fiber node 的时候发生了什么呢?

接下来我们看看详细的代码(这里的 workInProgress

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值