React18 中的 Suspense API使用实例详解

目录
  • 什么是新的 ReactJS Suspense API,什么时候应该使用它?
  • 什么是Suspense API?
  • 什么是 transition API?
  • 最后

什么是新的 ReactJS Suspense API,什么时候应该使用它?

何时使用:当组件开始变大并且您在同一页面上有许多组件时,您可能希望开始优化下载到客户端浏览器的方式和时间。

为此,React 为您提供了lazyAPI,它允许您将组件标记为lazy,这意味着被lazy包裹的组件,将会在第一次真正使用时被加载,而不是页面初始化的时候。

懒加载优化是减少“首屏渲染时间”和其他指标的绝妙方法,这些指标主要是用于衡量应用程序首次渲染所需的时间以及“准备好”交互所需的时间。

但是当你使用这种优化时,你会遇到一个问题:如果组件下载时间过长会发生什么?尤其是在网速较慢的情况下。在这种情况下,界面应该展示什么?即使用户看不到,我们该如何让用户知道当前界面正在发生的事情呢?

这就是 Suspense API 发挥作用的地方,让我们来看看吧!

什么是Suspense API?

Suspense API 与“lazy”组件结合使用时,可以让用户知道,此时当前界面正在后台加载某些内容。 当浏览器在下载需要懒加载的这个组件的过程中,提供替代可视化(不同的组件)来做到这一点。

这里的前提是,这个替代组件(一般loading组件)是一个较低的较小的,并且很可能可以在许多不同的地方重复使用的组件。这样话,权衡是有意义的。

对于本文,我创建了一个 Github 存储库,在分支react18-suspense中!

使用时,需要你简单地用 Suspense 包装你的lazy组件,同时指定 fallback 属性。像这样:

import React, { Suspense, useState } from "react";
import Waiting from "./waiting";
const Text = React.lazy(() => import("./text"));
const Buttons = React.lazy(() => import("./buttons"));
export default function Tabs() {
  const [tab, setTab] = useState("text");
  return (
    <Suspense fallback={<Waiting />}>
        <div style={{ minWidth: "40vw" }}>
        <p>
          <a
            href="#" rel="external nofollow"  rel="external nofollow"
            onClick={(_) => {
              if (tab == "text") setTab("buttons");
              else setTab("text");
            }}
          >
            Toggle to {tab === "text" ? "buttons" : "text"}
          </a>
        </p>
        <div style={{ minWidth: "40vw" }}>
          {tab === "text" ? <Text /> : <Buttons />}
        </div>
      </div>
    </Suspense>
  );
}

从以上代码中可以看出,Text 和 Buttons 组件都是会懒加载的,加载它们中的任何一个都需要向服务器发出请求。点击 “Toggle”,可以在两者之间交替。

现在有趣的是,Suspense 组件不必直接包装懒加载的组件。它们可以在树的多个层次上,无论如何都会显示fallback。所以你不必担心用它包装每一个组件,你可以包装你的组件树的整个部分,并让它们都使用相同的fallback。

看上面的 GIF图,它以白屏开始,因为它下载初始页面的速度很慢(请注意“网络”选项卡上的“slow 3G”设置)。紧接着,我们会看到“Waiting...”消息,这就是 Waiting fallback。

然后它被一条文本消息替换,即加载的文本组件。我们在这里看到了 Suspense API 的实际应用。

然后,当我单击“切换”链接时,将再次看到“waiting...”消息几秒钟,而浏览器正在第一次下载按钮组件。

在此之后,组件之间的切换是立即执行的,因为它们已经加载,并且不再需要 Suspense API。

如果你想了解更多关于 Suspense 的信息,我建议你阅读此处的 RFC,因为它为你提供了理解该功能所需的所有上下文。

什么是 transition API?

有兴趣的可以移步这篇介绍useTransition的文章!

作为 React 18 的一部分,Suspense API 增加了一个,它允许您以在某些情况下可能对用户更友好的方式在组件之间进行转换。

如果你回到我们的示例,会注意到,每次单击“Toggle”时,点击之前的旧组件消失了,取而代之的是界面上要么显示最新组件,要么显示“waiting...”,这样的交互,可能对用户来说变化太大了,因此我们可能希望保持点击之前,依然保持旧组件可见,并让用户可以与旧组件进行交互,同时 React在后台加载新组件。只有在新组件准备好后,它才会用它替换旧组件。

现在,您可以在 React 18 中使用 useTransition API 执行此操作,如下所示:

import React, { Suspense, useState, useTransition } from "react";
import Waiting from "./waiting";
const Text = React.lazy(() => import("./text"));
const Buttons = React.lazy(() => import("./buttons"));
export default function Tabs() {
  const [tab, setTab] = useState("text");
  const [isPending, startTransition] = useTransition();
  return (
    <Suspense fallback={<Waiting />}>
      <div style={{ minWidth: "40vw" }}>
        <p>
          <a
            href="#" rel="external nofollow"  rel="external nofollow"
            onClick={(_) => {
              startTransition(() => {
                if (tab == "text") setTab("buttons");
                else setTab("text");
              });
            }}
          >
            My Toggle to {tab === "text" ? "buttons" : "text"}
          </a>
        </p>
        <div style={{ opacity: isPending ? 0.1 : 1, minWidth: "40vw" }}>
          {tab === "text" ? <Text /> : <Buttons />}
        </div>
      </div>
    </Suspense>
  );
}

这是完全相同的代码,但是现在当我们单击“Toggle”时,我们调用 startTransition 来切换tab,这样告诉 React 只有在加载完成后才替换组件。

因为缺少了loading状态,可能会让用户有点困惑,所以我们可以从 useTransition 钩子返回的 isPending 中获取。这个isPending可以用来表示当前组件正在发生一些事情,而不会完全破坏用户的体验。在我的例子中,我将“旧”组件的不透明度设置为“0.1”,同时加载“新”组件。

现在,如果要运行此示例,你将看到第一次刷新页面的时候触发了fallback,然后每当用户手动单击“Toggle”时,都会调用startTransition。这为用户提供了更好的体验,并且仍然尽可能优化。

最后

Suspense API 并不复杂,也不会给你现有的项目添加太多代码。但是,如果你的应用程序不够复杂,你可能不需要使用它。

要确定代码中是否应该使用,我们应该问自己的第一个问题是:我在每个页面上渲染了多少个组件,以及为此加载了多少个组件?要分析我们的应用程序的性能,并确定这些组件是否确实导致了一些初始加载时间问题。如果是这样,那么行的,开始代码拆分并引入吧!否则,你可以不使用也没事。

以上就是React18 中的 Suspense API使用实例详解的详细内容,更多关于React18 Suspense API的资料请关注我们其它相关文章!

(0)

相关推荐

  • React Suspense前后端IO异步操作处理

    目录 简单介绍Suspense Suspense主要用法和场景 一. React18之前的做法 二. React18之后 Suspense配合前端表格组件处理前后端IO异步操作 简单介绍Suspense Suspense主要用来解决网络IO问题,它早在2018年的React 16.6.0版本中就已发布.它的相关用法有些已经比较成熟,有的相对不太稳定,甚至经历了重命名.删除: 在render函数中,我们可以写入一个异步请求,请求数据 react会从我们缓存中读取这个缓存 如果有缓存了,直接进行正常

  • react中Suspense的使用详解

    关于Suspense的使用,先来看下示例代码 const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> </div&

  • react  Suspense工作原理解析

    目录 Suspense 基本应用 Suspense 原理 基本流程 源码解读 - primary 组件 源码解读 - 异常捕获 源码解读 - 添加 promise 回调 源码解读-Suspense 首次渲染 primary 组件加载完成前的渲染 primary 组件加载完成时的渲染 利用 Suspense 自己实现数据加载 Suspense 基本应用 Suspense 目前在 react 中一般配合 lazy 使用,当有一些组件需要动态加载(例如各种插件)时可以利用 lazy 方法来完成.其中

  • React中Suspense及lazy()懒加载及代码分割原理和使用方式

    目录 React.lazy() 概括 为什么需要懒加载 如何进行代码分割 Suspense Suspense应用场景 Suspense实现原理 总结 Suspense和lazy()都是react中比较新的特性,在项目中使用还比较少,但是学习一下有助于在后面的项目中使用,同样可以一窥React未来的发展方向 React.lazy() 概括 顾名思义lazy()方法是用来对项目代码进行分割,懒加载用的.只有当组件被加载,内部的资源才会导入 为什么需要懒加载 在React的项目中import导入其他组

  • React18 中的 Suspense API使用实例详解

    目录 什么是新的 ReactJS Suspense API,什么时候应该使用它? 什么是Suspense API? 什么是 transition API? 最后 什么是新的 ReactJS Suspense API,什么时候应该使用它? 何时使用:当组件开始变大并且您在同一页面上有许多组件时,您可能希望开始优化下载到客户端浏览器的方式和时间. 为此,React 为您提供了lazyAPI,它允许您将组件标记为lazy,这意味着被lazy包裹的组件,将会在第一次真正使用时被加载,而不是页面初始化的时

  • python+requests+unittest API接口测试实例(详解)

    我在网上查找了下接口测试相关的资料,大都重点是以数据驱动的形式,将用例维护在文本或表格中,而没有说明怎么样去生成想要的用例, 问题: 测试接口时,比如参数a,b,c,我要先测a参数,有(不传,为空,整形,浮点,字符串,object,过短,超长,sql注入)这些情况,其中一种情况就是一条用例,同时要保证b,c的正确,确保a的测试不受b,c参数的错误影响 解决思路: 符合接口规范的参数可以手动去填写,或者准备在代码库中.那些不符合规范的参数(不传,为空,整形,浮点,字符串,object,过短,超长,

  • java 并发中的原子性与可视性实例详解

    java 并发中的原子性与可视性实例详解 并发其实是一种解耦合的策略,它帮助我们把做什么(目标)和什么时候做(时机)分开.这样做可以明显改进应用程序的吞吐量(获得更多的CPU调度时间)和结构(程序有多个部分在协同工作).做过java Web开发的人都知道,Java Web中的Servlet程序在Servlet容器的支持下采用单实例多线程的工作模式,Servlet容器为你处理了并发问题. 原子性 原子是世界上的最小单位,具有不可分割性.比如 a=0:(a非long和double类型) 这个操作是不

  • C++ 中const修饰虚函数实例详解

    C++ 中const修饰虚函数实例详解 [1]程序1 #include <iostream> using namespace std; class Base { public: virtual void print() const = 0; }; class Test : public Base { public: void print(); }; void Test::print() { cout << "Test::print()" << end

  • AngularJS中使用three.js的实例详解

    AngularJS中使用three.js的实例详解 一.轨迹球的引入问题 一开始我是用下面的方式引如轨迹球,但是会报Trackballcontrols is undefined的错. import * as THREE from 'three'; import * as Trackballcontrols from 'three'; 但其实我是能够在node_module下的threejs的包中找到Trackballcontrols的文件的,我一开始以为是引用的路径没对然后修改路径到对应包下Tr

  • IOS 中CALayer绘制图片的实例详解

    IOS 中CALayer绘制图片的实例详解 CALayer渲染内容图层.与UIImageView相比,不具有事件响应功能,且UIImageView是管理内容. 注意事项:如何使用delegate对象执行代理方法进行绘制,切记需要将delegate设置为nil,否则会导致异常crash. CALayer绘制图片与线条效果图: 代码示例: CGPoint position = CGPointMake(160.0, 200.0); CGRect bounds = CGRectMake(0.0, 0.0

  • vue中v-model动态生成的实例详解

    vue中v-model动态生成的实例详解 前言: 最近在做公司的项目中,有这么一个需求,每一行有一个input和一个select,其中行数是根据服务器返回的json数据动态变化的.那么问题来了,我们要怎样动态生成v-model? 现在项目做完了就整理了一下,直接贴代码了. <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <

  • Linux 中常用的Rpm命令实例详解

    rpm命令是RPM软件包的管理工具.rpm原本是Red Hat Linux发行版专门用来管理Linux各项套件的程序,由于它遵循GPL规则且功能强大方便,因而广受欢迎.逐渐受到其他发行版的采用.RPM套件管理方式的出现,让Linux易于安装,升级,间接提升了Linux的适用度. 语法 rpm(选项)(参数) 选项 -a:查询所有套件: -b<完成阶段><套件档>+或-t <完成阶段><套件档>+:设置包装套件的完成阶段,并指定套件档的文件名称: -c:只列出

  • Linux 中fork的执行的实例详解

    Linux 中fork的执行的实例详解 先看看一段fork的程序 int main() { pid_t pid; 语句 a; pid = fork(); 语句 b; } 1.当程序运行到 pid = fork()时,这个进程马上分裂(fork的中文意思)成两个进程,我们称为父进程和子进程,子进程是父进程的副本,副本的意思是子进程把父进程的数据空间,堆和栈都复制一遍给自己用,这要求在内存给子进程分配和父进程同样大的存储空间,这样,父,子进程拥有相同的数据,但不会共享存储空间,他们只是共享正文段.

  • java 中HttpClient传输xml字符串实例详解

    java 中HttpClient传输xml字符串实例详解 介绍:我现在有一个对象page,需要将page对象转换为xml格式并以binary方式传输到服务端 其中涉及到的技术点有: 1.对象转xml流 2.输出流转输入流 3.httpClient发送二进制流数据 POM文件依赖配置 <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifact

随机推荐