你是不是也常搞混這兩句?
「用 React.lazy 就要搭 Suspense 啊~」
「Suspense 可以等資料載入嗎?」
很多人以為 Suspense
只是拿來顯示 Loading...
。
但在 React 18 之後,它其實變成了一個「通用等待機制」。
今天我們就一次弄清楚:
React.lazy()
到底在等什麼?Suspense
又是怎麼幫它(或其他 Promise)處理的?
React.lazy()
會回傳一個會在 render 階段「丟出 Promise」的 component。
當 React 發現這個 Promise 時,會交給 <Suspense>
處理,顯示 fallback,
直到 Promise 完成,再重新 render 真正內容。
而在 React 18 的 Server Component 世界裡,
任何 async function component
也可能在 render 丟 Promise(例如 fetch 資料)。
此時 Suspense
一樣會介入,先渲染 fallback,待資料回來再更新畫面。
'use client';
export default function Profile() {
const data = fetch('/api/user').then(r => r.json()); // ❌ 無法在 render 等
return <div>{data.name}</div>;
}
fetch()
在瀏覽器是非同步,React 無法在 render 階段等它,
因此這段程式不會被 Suspense 捕捉。
'use client';
import { lazy, Suspense } from 'react';
const Chart = lazy(() => import('./Chart'));
export default function Dashboard() {
return (
<Suspense fallback={<p>Loading chart...</p>}>
<Chart />
</Suspense>
);
}
// app/UserList.jsx
export default async function UserList() {
const users = await fetch('https://api.example.com/users').then(r => r.json());
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}
// app/page.jsx
import { Suspense } from 'react';
import UserList from './UserList';
export default function Page() {
return (
<Suspense fallback={<p>Loading users...</p>}>
<UserList />
</Suspense>
);
}
誤解 | 真相 |
---|---|
Suspense 只能配 React.lazy | React 18 開始可等任何 Promise(含 Server 資料)。 |
lazy 可以在 Server 用 | ❌ Server 不用下載 JS,lazy 僅限 Client。 |
Suspense 會等 useEffect 裡的 fetch | ❌ useEffect 在 render 後才跑,React 等不到。 |
React.lazy
分割大 bundle,減少初始載入時間。1️⃣ 試著把一個大型 chart 或 editor 元件改寫成 React.lazy()
載入。
2️⃣ 在 Next.js App Router 中建立一個 async Server Component,
用 <Suspense>
包起來,觀察 fallback 在 stream 時的行為。
中文
React.lazy
用來延遲載入 JS 模組,是 client-side 的 code splitting。<Suspense>
則是 React 用來捕捉 Promise 並顯示 fallback 的機制。
在 React 18 中,Suspense 也能在 Server 等待 async component 的 fetch。
簡單說:lazy 產生 Promise,Suspense 處理 Promise。
英文
React.lazy is for client-side code splitting — it throws a Promise while loading a JS chunk.
Suspense is the mechanism that React uses to catch that Promise and show a fallback.
In React 18, Suspense can also handle async Server Components that fetch data before rendering.
✅ React.lazy()
= client 端 JS 懶載入(code splitting)
✅ <Suspense>
= React 的 Promise 等待機制(server + client 通用)
✅ lazy 產生 Promise,Suspense 負責 fallback 與 重新 render。
✅ React 18 讓 Suspense 能 等待 Server 端的 資料抓取與 Streaming SSR。