React16源码: Suspense与lazy源码实现

2024-01-02 05:04

本文主要是介绍React16源码: Suspense与lazy源码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Suspense 与 lazy


1 )概述

  • Suspense 是在 react16.6 提供的新 feature
  • 用于加载的缓冲的内置组件

2 )示例程序

lazy.js

// lazy.js
import React from 'react'
export default () => <p>Lazy Comp</p>

主程序

import React, { Suspense, lazy } from 'react'const LazyComp = lazy(() => import('./lazy.js'))let data = ''
let promise = ''
function requestData() {if (data) return dataif (promise) throw promisepromise = new Promise(resolve => {setTimeout(() => {data = 'Data resolved'resolve()}, 2000)})throw promise
}function SuspenseComp() {const data = requestData()return <p>{data}</p>
}export default () => (<Suspense fallback="loading data"><SuspenseComp /><LazyComp /></Suspense>
)
  • 示例的效果是先显示的是 loading data,然后再显示出来 Data resolved
  • 最终 export出去的这个组件,它是一个 function component
    • 里面使用了 Suspense,然后给它一个 fallback 的 prop
    • 这就是我们看到的 loading data,里面是一个组件(SuspenseComp),也是一个function component
    • 调用了一个 requestData 方法,它渲染的是一个p标签, 填充 data
  • 可以在一个 Suspense 组件,下面渲染一个或者多个这种异步的组件
    • 有任何一个抛出了 promise以及在这个 promise relove 之前
    • 都会显示这个 fallback里的内容
  • 这就是 Suspense 组件的一个原理
    • 其实它具体的内部实现是非常复杂的
  • 注意,16.6版本的React只支持lazy就是异步加载组件
    • 并没有很好的去支持我们的异步数据加载的功能
    • 相关源码没有稳定,跟数据加载相关的是 Suspense 的功能后期发布
    • 在后面的版本进行使用,当前版本是不推荐在生产环境使用
  • Suspense支持 lazy组件,可以非常方便的实现异步组件加载
    • 配合webpack提供的 import 来实现这个功能
    • 比如代码中, const LazyComp = lazy(() => import('./lazy.js'))
    • 这个 LazyComp 也被放到这个 Suspense 里面
  • 在控制台的 network 面板里面,刷新一下
    • 可以看到bundle.js 然后 2.chunk.js
    • 这就是我们进行了一个异步加载组件,自动给我们区分的一个 js 文件
  • 因为其实我们是在本地开发的,异步加载速度非常快
    • 最终 LazyComp 跟 Data resolved 是一起显示出来的
    • 如果在 Suspense 组件内部有多个组件,要等到所有的组件都resolved之后
    • 它才会把fallback里面的内容移除,这是 Suspense 的一个特点
    • 如果里面任何一个组件处于 pending 状态,它还是会显示 fallback

3 ) 源码探究

  • 定位到 React.js, 找到 Suspense

     import {REACT_SUSPENSE_TYPE,} from 'shared/ReactSymbols';import { lazy } from './ReactLazy';const React = {// ... 此处省略其他lazy,// ... 此处省略其他Suspense: REACT_SUSPENSE_TYPE}
    
    • 看到 Suspense它是一个常量,就是一个 REACT_SUSPENSE_TYPE,本质上只是一个Symbol
    • 而 lazy 就不是一个Symbol 了
    • 我们可以看到 import { lazy } from './ReactLazy';
  • 基于这个,定位到 ReactLazy.js 查看 lazy 源码

    /*** Copyright (c) Facebook, Inc. and its affiliates.** This source code is licensed under the MIT license found in the* LICENSE file in the root directory of this source tree.*/import type {LazyComponent, Thenable} from 'shared/ReactLazyComponent';import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {return {$$typeof: REACT_LAZY_TYPE,_ctor: ctor,// React uses these fields to store the result._status: -1,_result: null,};
    }
    
  • 它是一个方法 export function lazy,并接收一个方法

    • lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T>
    • 它指定这个传入的参数,这个参数是一个方法,并且它要返回一个 Thenable 类型的对象
    • Thenable 是 Promise 这样的一个对象,它具有 .then 方法
  • 最终,返回的是一个 lazy component

    • $$typeof,值为 REACT_LAZY_TYPE
    • _ctor 就是我们传递进来的回调函数
      • 在react渲染的过程当中,渲染到 lazy component 的时候
      • 会去调用这个 _ctor 回调,并返回一个 Thenable 的对象(Promise对象)
      • 这个时候Promise是处于 pending 状态的,对应的是值是 -1
    • _status 用来记录当前这个 Thenable 的对象,所处的状态
      • 后续达到了resolved 或者是 rejected 的这两种状态的时候,这个 _status 会变化
      • 让后期进行渲染的时候可以进行不一样的处理
    • _resultPromise结果
      • 用来记录这个Thenable对象,它 resolve 之后返回的那个属性
      • 在 lazy 里面,最终的组件会挂载到这个 _result
      • 后续渲染这个 lazy 组件的时候,直接拿 _result 里面的组件渲染就可以了

这篇关于React16源码: Suspense与lazy源码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/561407

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get