簡單介紹 lazy 跟 Suspense 的用途跟用法
lazy 是 react 裡面提供的一個 api 可以讓我們透過非同步的方式載入 JavaScript,隨著專案的發展可能會有很多分頁跟資料,如果要在用戶第一次進到網頁時就全部進行載入可能會有很長的讀取跟解析時間。
import { useState } from "react";
import PageOne from "./PageOne";
import PageTwo from "./PageTwo";
function App() {
const [page, setPage] = useState("");
function handlePage(page: string) {
setPage(page);
}
return (
<div>
<div>
<button onClick={() => handlePage("PageOne")}>One</button>
<button onClick={() => handlePage("PageTwo")}>Two</button>
</div>
{
{
"": <>HOME</>,
PageOne: <PageOne />,
PageTwo: <PageTwo />,
}[page]
}
</div>
);
}
我在 App 裡面引入了 PageOne 跟 PageTwo 兩個元件,透過 button 來控制要顯示哪個元件。
在 pagOne 跟 pageTwo 裡面分別載入了較大的 json 檔案。
// PageTwo 的內容基本上相同。
import data from "../public/data-1.json";
function PageOne() {
console.log("data", data);
return <div>Here is Page One!!!</div>;
}
export default PageOne;
打開瀏覽器開發者工具,點擊 network 的分頁可以看到載入了哪些檔案。
可以看到即使畫面沒有顯示元件,但是一樣把元件也一起載入了,當然裡面如果有引入比較大的檔案也會一起事先載入,透過 lazy 就可以在需要的時候再載入你的 react 元件。
const SomeComponent = lazy(load)
load
: 一個 function 回傳 Promise 物件或其他 thenable 的物件,react 只會呼叫這個 function 在這個元件需要被放在畫面上的時候,react 只會呼叫一次並把回傳的結果保留下來,不會重複呼叫相同的內容。
SomeComponent
: 回傳可以被非同步載入的 react 元件。
<Suspense>
跟 <Fragment> (<>...</>)
一樣都是 react 提供的元件,Suspense 讓我們在元件在載入的過程中有預設的內容可以顯示。
<Suspense fallback={<Loading />}>
<SomeComponent />
</Suspense>
Suspense 元件接收兩個 props,children
跟 fallback
。
children
: 希望可以非同步載入的元件跟內容,如果元件還在解析的話會先顯示 fallback 的內容。fallback
: 一個備用的元件,讓我們在 children
還在載入的過程時可以保持正常的 render 流程,Suspense 元件會自動的在這兩個 props 中進行切換。
簡單看過了 lazy 跟 Suspense 的用法之後就可以讓我們上面的元件做到非同步的載入了。
import { useState, lazy, Suspense } from "react";
const PageOne = lazy(() => import("./PageOne"));
const PageTwo = lazy(() => import("./PageTwo"));
function Loading() {
return <p>Loading...</p>;
}
function App() {
const [page, setPage] = useState("");
function handlePage(page: string) {
setPage(page);
}
return (
<div>
<div>
<button onClick={() => handlePage("PageOne")}>One</button>
<button onClick={() => handlePage("PageTwo")}>Two</button>
</div>
{
{
"": <>HOME</>,
PageOne: (
<Suspense fallback={<Loading />}>
<PageOne />
</Suspense>
),
PageTwo: (
<Suspense fallback={<Loading />}>
<PageTwo />
</Suspense>
),
}[page]
}
</div>
);
}
本來的 import
改成了 const PageOne = lazy(() => import("./PageOne"));
的形式。
另外也多了 Loading 的元件放在 <Suspense fallback={<Loading />}>
裡面。
可以看到當我載入畫面的時候 PageOne 跟 PageTwo 還有裡面 import 的檔案都沒有被載入,而是等到我點擊按鈕切換元件的時候才被載入,而且已經被載入的元件就不會重複的載入,透過非同步載入的方式可以大大的提高網頁的效能跟載入速度。
lazy - react document<Suspense>
- react document
下一篇會介紹 react 常用的相關套件 - react router
如果內容有誤再麻煩大家指教,我會盡快修改。
這個系列的文章會同步更新在我個人的 Medium,歡迎大家來看看 👋👋👋
Medium