React16源码: React中的setState和forceUpdate源码实现

这篇具有很好参考价值的文章主要介绍了React16源码: React中的setState和forceUpdate源码实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

setState 和 forceUpdate


1 ) 概述

  • 通过 class component 内部的 setState,以及 forceUpdate 去更新一个组件的过程
  • 在react的应用当中,我们只有 ReactDOM.render setState,以及 forceUpdate
  • 这几种种方式去更新react的应用是合理的,其他没有什么特别常用的方式去更新了
  • 而且react官方推荐的也是用这些。forceUpdate 其实本身也不是特别推荐的
  • 因为有比较特殊的作用,以及比较特殊的使用场合, 也算是一个比较有用的API
  • 在React16.7之后发布的Hooks, Hooks里面我们通过
  • useState 返回过来的一个方法,也可以去更新一个组件的状态
    • 这块看不到源码,只能看到打包之后的代码
    • 它的设置比较特殊,这块先跳过
  • setState,以及 forceUpdate的核心,首先是他们是给节点 Fiber 去创建更新的
  • 对于 ReactDOM.render 来说,它创建的 update 是放在root上面
  • 它是一个整体的渲染,因为执行 ReactDOM.render 的时候
  • 整个应用都没有任何的产生,任何的节点都没有生成,是一个初始的渲染
  • 所以 setStateforceUpdate 是针对某一个 class component 来说的
    • 这个 class component 的状态来进行更新
    • 把新的状态计算并渲染出来
  • setStateforceUpdate 两者更新的类型不同
    • 它们上面有 UpdateState, ForceUpdate 两种不同的 tag
    • 这个tag就对应的它们是更新的类型不同

2 )源码

  • 先跳过 组件如何去渲染

    • 也就是我们的 class component,什么时候会被实例化
    • 这个涉及到后面的更新的流程
  • 我们的component的BaseClass在初始化的时候会拿到一个update的这个对象

  • 这个对象来自于哪个地方

  • 源码: https://github.com/facebook/react/blob/v16.6.0/packages/react-reconciler/src/ReactFiberClassComponent.js

  • 这个文件中,有涉及很多 class 相关的代码

    const classComponentUpdater = {
      isMounted,
      enqueueSetState(inst, payload, callback) {
        const fiber = ReactInstanceMap.get(inst); // inst 是调用 this.setState 时的 this,在react渲染的时候会通过 `ReactInstanceMap` 做映射和获取 Fiber对象
        const currentTime = requestCurrentTime();
        const expirationTime = computeExpirationForFiber(currentTime, fiber);
    
        const update = createUpdate(expirationTime);
        update.payload = payload; // 这里 payload 是 setState时传入的对象
        if (callback !== undefined && callback !== null) {
          if (__DEV__) {
            warnOnInvalidCallback(callback, 'setState');
          }
          update.callback = callback; // 挂载 callback
        }
    
        enqueueUpdate(fiber, update); // 把fiber对象的updateQueue进行初始化或更新
        scheduleWork(fiber, expirationTime); // 进行调度处理
      },
      enqueueReplaceState(inst, payload, callback) {
        const fiber = ReactInstanceMap.get(inst);
        const currentTime = requestCurrentTime();
        const expirationTime = computeExpirationForFiber(currentTime, fiber);
    
        const update = createUpdate(expirationTime);
        update.tag = ReplaceState;
        update.payload = payload;
    
        if (callback !== undefined && callback !== null) {
          if (__DEV__) {
            warnOnInvalidCallback(callback, 'replaceState');
          }
          update.callback = callback;
        }
    
        enqueueUpdate(fiber, update);
        scheduleWork(fiber, expirationTime);
      },
      enqueueForceUpdate(inst, callback) {
        const fiber = ReactInstanceMap.get(inst);
        const currentTime = requestCurrentTime();
        const expirationTime = computeExpirationForFiber(currentTime, fiber);
    
        const update = createUpdate(expirationTime);
        update.tag = ForceUpdate;
    
        if (callback !== undefined && callback !== null) {
          if (__DEV__) {
            warnOnInvalidCallback(callback, 'forceUpdate');
          }
          update.callback = callback;
        }
    
        enqueueUpdate(fiber, update);
        scheduleWork(fiber, expirationTime);
      },
    };
    
    • 这里面主要关注, enqueueSetStateenqueueForceUpdate 这两个enqueue 方法几乎一样,两者区别 看 update.tag
    • 看了上面的源码,发现 和 react-reconciler/src/ReactFiberReconciler.js 中的 updateContainer 很像
      • 内部调用 updateContainerAtExpirationTime 接着调用 scheduleRootUpdate 在这里面都基本相似
  • 所以,在React中创建更新的过程都是差不多的,创建完更新后,进入队列,就会进行整个应用的更新

  • React 是一个非常纯粹的框架,所有的核心都是服务应用的整体更新的, 就是 scheduleWork 函数进入之后的整体更新流程

  • 这块在React整体的代码量中占据非常大的比例文章来源地址https://www.toymoban.com/news/detail-824298.html

到了这里,关于React16源码: React中的setState和forceUpdate源码实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React16源码: React中的performWork的源码实现

    performWork 1 )概述 performWork 涉及到在调度完成,或者同步任务进来之后整个 root 节点链条如何更新 怎么更新一棵 Fiber 树,它的每一个节点是如何被遍历到,以及如何进行更新操作 A. 在执行 performWork 时候,是否有 deadline 的区分 deadline 是通过 reactschedule 它的一个时间片,更新

    2024年01月17日
    浏览(25)
  • React16源码: React中的reconcileChildren的源码实现

    reconcileChildren 1 )概述 在更新了一个节点之后,拿到它的props.children 要根据这个children里面的 ReactElement 来去创建子树的所有的 fiber 对象 要根据 props.children 来生成 fiber 子树,然后判断 fiber 对象它是否是可以复用的 因为我们在第一次渲染的时候,就已经渲染了整个 fiber 子树

    2024年01月20日
    浏览(28)
  • React16源码: React中的updateClassComponent的源码实现

    ClassComponent 的更新 1 ) 概述 在 react 中 class component,是一个非常重要的角色 它承担了 react 中 更新整个应用的API setState forceUpdate 在react当中,只有更新了state之后,整个应用才会重新进行渲染 在 class component 中, 它的逻辑相对复杂 2 )源码 在 packages/react-reconciler/src/ReactFiberB

    2024年01月21日
    浏览(25)
  • React16源码: React中的beginWork的源码实现

    beginWork 1 )概述 在 renderRoot 之后,要对我们的 Fiber 树每一个节点进行对应的更新 更新节点的一个入口方法,就是 beginWork 这个入口方法会有帮助我们去优化整棵树的更新过程 react 它的节点其实是非常多的,如果每一次子节点的一个更新 就需要每一个节点都执行一遍更新的话

    2024年01月20日
    浏览(33)
  • React16源码: React中的renderRoot的源码实现

    renderRoot 1 )概述 renderRoot 是一个非常复杂的方法 这个方法里处理很多各种各样的逻辑, 它主要的工作内容是什么? A. 它调用 workLoop 进行循环单元更新 遍历整个 Fiber Tree,把每一个组件或者 dom 节点对应的 Fiber 节点拿出来单一的进行更新,这是一个循环的操作 把整棵 Fiber T

    2024年01月17日
    浏览(28)
  • React16源码: React中的HostComponent & HostText的源码实现

    HostComponent HostText 1 )概述 HostComponent 就是我们dom原生的这些节点, 如: div, span, p 标签这种 使用的是小写字母开头的这些节点一般都认为它是一个 HostComponent HostText ,它是单纯的文本节点 主要关注它们的一个更新过程 2 )源码 定位到 packages/react-reconciler/src/ReactFiberBeginWork.js 进

    2024年01月24日
    浏览(28)
  • React16源码: React中的update和updateQueue的源码实现

    React中的update和updateQueue 1 )概述 在 ReactDOM.render 过程中,还需要创建一个 update 对象 update 用于记录组件状态的改变的一个对象,它存放于Fiber对象的 updateQueue 中 updateQueue ,它是一个单向链表的结构,一次整体的更新过程当中 可能在这个queue里会存在多 Update 在这次更新的过

    2024年02月02日
    浏览(25)
  • React16源码: React中的PortalComponent创建, 调和, 更新的源码实现

    PortalComponent 1 )概述 React Portal之所以叫Portal,因为做的就是和“传送门”一样的事情 render到一个组件里面去,实际改变的是网页上另一处的DOM结构 主要关注 portal的创建, 调和, 更新过程 2 )源码 定位到 packages/react-dom/src/client/ReactDOM.js#L576 这里调用的是 ReactPortal.createPortal ,

    2024年01月21日
    浏览(27)
  • React16源码: React中的reconcileChildIterator和reconcileChildrenArray的源码实现

    reconcileChildIterator 和 reconcileChildrenArray 1 )概述 在react更新某一个节点的时候,要根据这个节点,它的类型去获取它的children 比如说如果是 Function Component,它要调用这个 component 计算出它的return的属性 return的属性可能是一个数组,可能是单个的 ReactElement,可能是 number, string

    2024年01月20日
    浏览(24)
  • React16源码: React中的不同的expirationTime的源码实现

    不同的 expirationTime 1 )概述 在React中不仅仅有异步任务 大部分情况下都是同步的任务,所以会有不同 expirationTime 的存在 2 )种类 A. Sync 模式,优先级最高 任务创建完成之后,立马更新到真正的dom里面 是一个创建即更新的流程 B. Async 模式, 异步模式 会有一个调度 包含一系列

    2024年02月01日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包