網站首頁 編程語言 正文
什么是新的 ReactJS Suspense API,什么時候應該使用它?
何時使用:當組件開始變大并且您在同一頁面上有許多組件時,您可能希望開始優化下載到客戶端瀏覽器的方式和時間。
為此,React 為您提供了lazy
API,它允許您將組件標記為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="#" 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="#" 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 并不復雜,也不會給你現有的項目添加太多代碼。但是,如果你的應用程序不夠復雜,你可能不需要使用它。
要確定代碼中是否應該使用,我們應該問自己的第一個問題是:我在每個頁面上渲染了多少個組件,以及為此加載了多少個組件?要分析我們的應用程序的性能,并確定這些組件是否確實導致了一些初始加載時間問題。如果是這樣,那么行的,開始代碼拆分并引入吧!否則,你可以不使用也沒事。
原文鏈接:https://juejin.cn/post/7131695266461122596
相關推薦
- 2022-12-09 C++?如何將string轉換成全小寫_C 語言
- 2022-12-25 Redis過期鍵與內存淘汰策略深入分析講解_Redis
- 2022-04-08 在python中創建表格的兩種方法實例_python
- 2022-06-28 python神經網絡Keras構建CNN網絡訓練_python
- 2022-07-20 C語言雙向鏈表的原理與使用操作_C 語言
- 2022-12-26 python?時間處理之月份加減問題_python
- 2023-08-30 Git忽略已經提交過一次文件Git忽略文件
- 2022-08-11 C#中的composite模式示例詳解_C#教程
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支