[译] 实战 React 18 中的 Suspense

React 之 Suspense 进行异步网络请求,然后再拿到请求后的数据进行渲染是很常见的需求,但这不可避免的需要先渲染一次没有数据的页面,数据返回后再去重新渲染。组件来渲染子组件,这个组件的特性是能根据传入 mode 来控制子组件样式的显隐,这有一个好处,就是能保存组件的状态,有些许类似于 Vue 的。至此,Suspense 的一生我们粗略的过完了,在源码中对 Suspense 的处理非常多,涉及到优先级相关的本篇都略过。通过其需要的 mode 参数值,我们可以大胆的猜测,应该是一个能控制是否显示子组件的组件,如果。 阅读详情

8e854e09888d185ae437d518b3854457.jpeg

> 原文:https://dev.to/darkmavis1980/a-practical-example-of-suspense-in-react-18-3lln

React 18 带来了很多变化,它不会破坏你已经编写过的代码,并且有很多改进和一些新概念。

它也让很多开发人员,包括我,意识到我们错误地使用了useEffect hook。但话说回来,我们被其名称所误导了,因为实际上useEffect并不应该被用于副作用。

在 React 18 中,虽然仍然可以使用useEffect来完成一些事情,如使用 API 接口读取的数据填充状态,但实际上不应该将其用于此类目的。如果你在应用程序中启用StrictMode,在开发模式下,你将发现使用useEffect会被调用两次,因为现在React会mount 组件、卸载它,然后再次 mount 它,以检查代码是否运行正常。

Suspense 来了

我们应该用来取而代之的,是新的Suspense组件(虽然它已经存在于 React 17 中,但现在是推荐的方法),此组件将会按照以下方式工作:

<Suspense fallback={<p>Loading...</p>}>
  <MyComponent />
</Suspense>

上面的代码将会包裹一个组件,这个组件从某些数据源中加载数据,并在完成数据获取之前显示fallback。

Suspense 是什么

简而言之,可能和你想的不同,Suspense 并不是一个新的用于获取数据的接口,因为该工作仍然由诸如“fetch”或“axios”等库委派执行,而它实际上允许你将这些库与 React 集成,并且它的真正工作只是“在加载时显示这段代码,而在完成后显示那段代码”,仅此而已。

Suspense 如何工作

首先,你需要了解 Promise 的工作原理以及它的状态。无论使用传统方式new Promise()还是新的async/await语法来使用promise,在任何情况下,promise始终具有以下这三种状态:

  • pending -> 它仍在处理请求

  • resolved -> 请求已返回某些数据,我们获得了200 OK状态

  • rejected -> 出现了错误,获得了一个错误

Suspense使用的逻辑与ErrorBoundary完全相反,因此如果代码引发异常(因为它仍处于加载状态或者由于加载失败),则显示fallback;如果成功解析,则显示子组件。

举个例子

来看一个简单的例子,我们只需创建一个组件来获取API中的某些数据,并且希望在准备好后渲染该组件。

注意
为了简化,这里不会提到如何使用“startTransition”,添加错误边界,甚至不会涉及各种策略之间的区别,例如“fetch-on-render”、“fetch-then-render”等等...

包装 fetch 逻辑

如上所述,当我们的组件正在加载数据或失败时,需要抛出异常,但是一旦成功解决了Promise,就可以简单地返回响应。

为此,我们需要使用以下函数包装我们的请求:

// wrapPromise.js
/**
 * 将promise包装,以便可以与React Suspense一起使用
 * @param {Promise} 要处理的promise
 * @returns {Object} 与Suspense兼容的响应对象
 */
function wrapPromise(promise) {
  let status = 'pending';
  let response;

  const suspender = promise.then(
    res => {
      status = 'success';
      response = res;
    },
    err => {
      status = 'error';
      response = err;
    },
  );

  const handler = {
    pending: () => {
      throw suspender;
    },
    error: () => {
      throw response;
    },
    default: () => response,
  };

  const read = () => {
    const result = handler[status] ? handler[status]() : handler.default();
    return result;
  };

  return { read };
}

export default wrapPromise;

因此,上面的代码将检查我们Promise的状态,然后返回一个名为“read”的函数,稍后我们将在组件中调用它。

现在,我们需要使用它包装接口请求库(例子中是axios),创建一个非常简单的函数:

//fetchData.js
import axios from 'axios';
import wrapPromise from './wrapPromise';

/**
* 用wrapPromise函数包装Axios请求
* @param {string} 要获取的URL
* @returns {Promise} 包装的promise
*/
function fetchData(url) {
     const promise = axios.get(url).then(({data}) => data);

     return wrapPromise(promise);
}

export default fetchData;

这只是以接口请求库表现的一种抽象,我想强调这只是一种非常简单的实现,您可以将上面的所有代码扩展到任何需要做的工作中。在这里我使用了axios,但你可以根据自己的需要使用任何东西。

在组件中读取数据

当获取方面的所有内容都准备好后,我们来在组件中使用它。假设有一个简单的组件,只需从某个接口读取名称列表并打印。不同于习惯中在组件中通过useEffect钩子调用 fetch 的做法,这一次我们要直接在组件开始时(放在任何 hooks 之外),使用我们在包装器中导出的read方法来调用请求,因此我们的Names组件大概是这个样子的:

// names.jsx
import React from 'react';
import fetchData from '../../api/fetchData.js';

const resource = fetchData('/sample.json');
const Names = () => {
  const namesList = resource.read();

  // rest of the code
}

这里所做的是,当调用组件时,read()函数将开始抛出异常,直到完全解析完成;其后,会继续执行其余代码,在此例中也就是继续 render。所以该组件的全部代码如下:

// names.jsx
import React from 'react';
import fetchData from '../../api/fetchData.js';

const resource = fetchData('/sample.json');

const Names = () => {
  const namesList = resource.read();

  return (
    <div>
      <h2>List of names</h2>
      <ul>
        {namesList.map(item => (
          <li key={item.id}>
            {item.name}
          </li>))}
      </ul>
    </div>
  );
};

export default Names;

父组件

现在 Suspense 将要发挥作用了,首先需要在父组件中导入它:

// parent.jsx
import React, { Suspense } from 'react';
import Names from './names';

const Home = () => (
  <div>
    <Suspense fallback={<p>Loading...</p>}>
      <Names />
    </Suspense>
  </div>
);

export default Home;

到底肿么了?
我们将Suspense作为React组件导入,然后使用它来包装获取数据的组件,在这些数据被 resolve 之前,它将只会渲染“fallback”组件,因此只是<p>Loading...</p>或其他什么你需要的自定义组件。

结论

长时间使用useEffect以实现相同的结果后,当我第一次看到 Suspanse 这种用法时,我对这种新方法有些怀疑。包装获取库的整个过程有点让人生疑。但是现在,我可以看到它的好处,它非常容易处理加载状态,它抽象掉了一些代码,使其易于重用,并通过消除(好吧,至少在大多数情况下)组件本身的“useEffect”钩子简化了组件的代码,这在以前可是个让人头疼的事情。

c237d64a9700b8298c973fa50303460d.png925e0e5c844c123faa85c3cc81290170.png

React Suspense与lazy:异步渲染契约与代码分割实战 React 的异步渲染能力是现代前端性能优化的核心基础,其本质是将‘组件未就绪’这一运行时状态正式纳入协调与提交生命周期。Suspense 提供统一的异步占位机制,lazy 则作为声明式代码分割入口,二者共同构成 React 的异步渲染契约。该机制不仅支撑骨架屏、渐进式加载等用户体验优化,更深度依赖并发渲染模式、打包工具分块策略及 DOM 复用原理。在仪表盘、微前端、图表模块等典型场景中,合理运用 Suspense 边界与 lazy 加载,可显著提升 LCP、TTI 等核心 Web 指标。本文聚焦 Reac 阅读详情

相关推荐

React 18 就要来了,来看看发布计划

React 在今天刚刚在官网发布了有关于 React 18 的计划更新(The Plan for React 18 – React Blog),同时发布了 Alpha 版本的 npm 包: 下载地址:https://reactjs.org/blog/2021/06/08/the-plan-for-react-18.html 最近虽然忙到没时间做视频,不过这么大的事还是值得来聊聊(趁着公司电脑强制要求升 Big Sur 不让不让用的间隙……)。本文并非逐字翻译,一如既往的会带不少个人想法,不代表公司观..

hxvhx的博客 3076

React18新特性

React 团队在 2022 年 3 月 29 日正式发布了 React 的第 18 个版本。在这篇文章里简单介绍 React 18 的新特性,React Concurrent Mode(并发模式)的实现,以及简要的升级指南。

zz130428的博客 2413

IDEA中Maven工具栏与命令执行全攻略:高效开发必备技巧

IntelliJ IDEA 作为强大的 Java 开发工具,其 Maven 功能独具优势。Maven 工具栏位于工作区右侧,图标功能丰富,涵盖项目导入、源码处理、依赖操作等。执行 Maven 命令有多种途径,Run Anything 窗口可输入或选目标执行,上下文菜单能右键运行目标,还可创建运行配置,指定命令参数后运行,为开发者高效管理 Maven 项目、便捷执行命令提供有力支持。

2301_82300081的博客 2028

React18: 如何使用Suspense 等待数据异步加载

那么在Data fetching ,也就是等待数据异步加载的过程中,则需要对数据进行特殊的处理,现有的Relay框架,Next框架则已经支持这种格式,可以直接使用Suspense,这也是suspense 处于一个实验性阶段的原因之一,希望越来越多的框架可以支持suspense~。1:动态加载组件 (但这并不是一个react 18的新特性)有了这个函数之后,就可以对得到的promise对象进行处理。文中如果有任何问题欢迎大家交流与讨论~请求完成之后则会替换成相应的结果。才可以使用这个标签,

Coder小何 2579

Stata森林图进阶:个性化定制与高级技巧

本文详细介绍了Stata森林图的进阶技巧,包括个性化定制与高级应用。通过meta分析工具如metan命令,用户可以优化字体、颜色、坐标轴等视觉元素,提升森林图的专业性和可读性。文章还提供了黑白印刷设置、高分辨率导出等实用技巧,帮助科研人员制作符合学术出版要求的森林图。

ios99的博客 254

对于基本的捕鱼游戏设计思路(五)——鱼

今天讲捕鱼游戏里鱼的部分,也是比较关键的一部分。 一步一步来,先分析游戏,首先鱼是从屏幕外生成,然后它有个移动的动作,而且分为不同的类型。 然后就可以进入代码部分,首先设置一个计时器,控制时间生成鱼,而鱼分种类,所以就用到随机函数,随机输出一个值,传入switch语句,从而生成不同的鱼。 void GameScene::xiaoyuupdate(float dt){ Size visibl

Cineze的博客 1万+

React 18 新特性(二):Suspense & SuspenseList

本文介绍了 React 18 版本中 `Suspense` 组件和新增 `SuspenseList` 组件的使用以及相关属性的用法。并且和 18 之前的版本做了对比,介绍了新特性的一些优势。

浮沉半生的博客 2474

基于FPGA的PCIe核系列:FPGA root模式生成工程例子分析(1)

一、 PCIE系统架构 1.1 PCIE分层结构 PCIE结构 1.2 TLP包 四种TLP类型。 Memory (内存空间操作) IO (IO空间操作) Configuration (配置操作) Message (信息操作) 四种类型TLP,如果有需要响应,称为Non-Posted TLP,如果没有需要响应,称为Posted TLP。 TLP包类型 1.2.1 TLP结构 TLP数据格式 1.2.2 Header各个字段的含义 Header格式 ...

huangshanhu的博客 3432

如何在 React 18中 利用Suspense 实现 服务端渲染(SSR)

概述React 18 将包括对 其服务器端渲染 (SSR) 性能的架构做了改进。这些改进带来了实质性的效果,是几年来其团队工作的结晶。大多数的改进点都是在幕后进行的,但您需要了解一些选择加入机制,尤其是您在不适用框架的情况下。主要的新API是 pipeToNoWritable, 您可以在 "升级到服务器上的React18" 这篇文章中阅读了解。在最终的正式版本中,我们也将...

趣谈前端 1619

Facebook登录协议逆向实战:从加密参数到完整流程解析(附Python代码)

本文深入解析Facebook登录协议的逆向工程,重点拆解`lgndim`和`encpass`等加密参数的生成逻辑,并提供完整的Python实现代码。通过Base64解码和RSA加密技术,帮助开发者理解并实现Facebook登录流程,同时涵盖工程优化与安全实践。

weixin_30687051的博客 476

直流有刷电机控制 - 驱动电路(二)

1.如图所示为最常见的推挽驱动电路,我附加了具有正反转功能的电机驱动控制,正反转是由两个继电器组成。使用推挽电路来驱动NMOS管时充电电流和放电电流都很大,因此NMOS管导通快,关断也快,而且NMOS温度不会很高。下面来介绍一下该电路的原理。(1)PWM_MCU是由单片机给出的PWM波信号,该信号是由一些列高低电平的方波构成。当信号为高电平的时候Q3导通,经过R47再到Q5的g极,此时mos导通,如果是K1闭合是正转那么K2闭合就是反转。(2)当PWM低电平时使得Q3关断,Q6导通。

u011030644的博客 4719

React 18 的新特性:Concurrent Features 与 Suspense 深度解析

并发渲染指的是 React 可以同时开始多个渲染任务,但根据需要暂停或取消某些任务。与同步渲染相比,它更灵活,并显著提升了用户体验。例如,当用户输入表单数据时,React 会优先渲染这些高优先级的更新,而将低优先级的渲染任务推迟。Suspense是 React 提供的一个用于处理异步操作的工具。它允许开发者在数据加载过程中定义一个占位状态,从而提高用户体验。React 18 的 Concurrent Features 和 Suspense 让开发者能够更高效地管理异步操作与复杂更新任务。

一名热衷于技术的全栈开发者,专注于前端与后端的全面技术探索。在这里,我将分享我在技术领域的学习与成长,助力更多开发者的进步。 2602

CMake安装grpc生成gRPCTargets.cmake文件

以下是安装语句: cd grpc_folder git submodule update --init cmake .. make -j 4 sudo make install 然而编写依赖gRPC的程序,发现无法调用gRPC的CMake文件,错误提示如下所示: include could not find load file: /usr/local/lib/cmake/g...

2328

React Suspense底层原理揭秘

React Suspense 的核心原理是通过抛出 Promise 来协调异步操作,利用 Fiber 架构实现加载状态的智能调度。当遇到未完成的异步组件时,React 会捕获 Promise,显示 fallback UI,并在操作完成后重新渲染目标内容。这一机制深度集成了 React 的 Fiber 架构,支持并发渲染和服务端流式传输,让开发者能以同步代码风格处理异步逻辑,同时保持应用的响应性和流畅体验。

警警的博客 1386

海思3403烧结、复用及mic输入

3403调试的第一步是版本烧结,版本烧结经常遇到问题,本文记录总结遇到的各种问题。

平面到立体 1353

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Enzyme测试React 18悬念加载:Suspense边界测试

React 18引入的Suspense特性彻底改变了组件加载策略,但许多开发者在使用Enzyme进行测试时遇到了兼容性挑战。本文将深入分析Enzyme与React 18 Suspense的兼容性现状,提供实用的测试替代方案,并通过具体案例演示如何有效测试Suspense边界组件。 ## Enzyme与React 18的兼容性现状 Enzyme作为React生态中广泛使用的测试工具,其官方适配器...

gitblog_00752的博客 994

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

React 18 + React-RxJS:Suspense 深度集成实战,liftSuspense 让加载态化繁为简

React 18 的并发渲染带来了全新的 Suspense 机制,而 React-RxJS 正是为 React 提供 RxJS 响应式绑定的开源库——它通过 liftSuspense 操作符和 Subscribe 组件,把"加载中"直接变成数据流的一部分,让 React 18 的加载态处理化繁为简。本文将带你用最少的代码上手这套组合。 ## 为什么 React 18 需要响应式状态管理? 在

gitblog_00933的博客 195

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

React18介绍及setState、suspense、useTransition、useDeferredValue的使用

如果你有很多没那么着急的内容要渲染更新就可以使用此hook函数。它可以对于更新渲染进行降级,提高更重要的组件的提前渲染。

月光晒了很凉快的博客 1647

[译] React 18 新特性概览

[译] React 18 新特性概览 去年 React 17 发布的时候,一度被大家吐槽“无新特性”,因为没有添加任何面向开发人员的新功能,而主要侧重于升级简化 React 本身。那么即将到来的 React 18 又有哪些新特性呢? React 官方团队在近日成立了 React 18 工作组,并在6月9日发布了 React 18 发布计划: React 18 Alpha 版本 (现在可用) React 18 Beta 版本 (几个月后) React 18 RC 版本 (几个月后) Rea...

橘导的博客 1564

Lozad.js与React Suspense:React 18中的懒加载新范式

在现代Web应用开发中,性能优化始终是核心议题。随着React 18的发布,React Suspense(悬念)机制为组件级懒加载带来了革命性的简化,而Lozad.js作为轻量级原生懒加载库,在资源加载领域早已证明其价值。本文将深入探讨如何将这两种技术结合,构建React 18应用中的新一代懒加载方案,解决传统实现中代码分割与资源懒加载的协同难题。 ## 懒加载技术现状与挑战 传统前端开发中,...

gitblog_00767的博客 1086

【React】React 18:新特性与重大更新解析

并发渲染允许 React 同时准备多个版本的 UI。这意味着 React 可以在后台准备新的 UI,而不会阻塞主线程,从而保持应用的响应性。批处理是指 React 将多个状态更新组合成一次重新渲染,以提高性能。在 React 18 之前,批处理只在 React 事件处理程序中生效。现在,所有的更新都会自动批处理,无论它们来自哪里。Transitions 允许开发者将某些更新标记为"可中断"的,这意味着这些更新可以被更紧急的更新打断。

鑫宝的博客 2442

React 18 并发渲染实战:useTransition、Suspense 与自动批处理深度解析

React 18并发渲染实战:useTransition、Suspense与自动批处理深度解析 本文深入探讨React 18三大并发特性: useTransition:通过标记低优先级更新解决界面卡顿问题,使输入框等高频交互保持流畅 Suspense:配合React Query实现声明式异步数据加载,消除分散的loading状态管理 自动批处理:优化渲染性能,减少不必要的重复渲染 文章通过具体代码示例演示了: 如何使用useTransition优化大列表搜索场景 正确组合Suspense与React Que

三声三视的博客 494

How i can get suspense to work on react 18?

如何在 React 18 中使 Suspense 生效?

suiusoar 1010

React并发模式终极指南:Suspense在gh_mirrors/aw/awesome-react-hooks中的应用

在当今的前端开发中,React并发模式已经成为提升应用性能和用户体验的关键技术。gh_mirrors/aw/awesome-react-hooks项目作为React Hooks资源的权威集合,为我们展示了如何在现代React应用中充分利用Suspense特性来实现更流畅的用户体验。 ## 什么是React并发模式? React并发模式是React 18引入的革命性特性,它允许React在渲染过

gitblog_00915的博客 1026

React 并发模式深度解析:从 Fiber 架构到 Suspense 落地实践

场景是否推荐并发模式原因大型数据表格/列表的实时过滤推荐过滤渲染可降级为低优先级,保证输入流畅复杂表单的实时校验与预览推荐校验结果可延迟渲染,不阻塞用户输入简单展示页面(<100 节点)不推荐调度开销大于收益需要严格原子性渲染的金融图表谨慎中间状态可能导致错误的数据展示SSR 场景需配合流式 SSR传统 SSR 不支持并发,需升级为 Streaming SSR。

weixin_49475940的博客 4334
上一篇: [译] React 中的 "最新 Ref 模式"
下一篇: Web Component -- 即将爆发的原生的 UI 组件化标准
云前端
博客等级 码龄17年 101粉丝 113原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值