客戶端元件 (Client Components)

客戶端元件 (Client Components) 讓你能夠編寫互動式 UI,並在請求時於客戶端進行渲染。在 Next.js 中,客戶端渲染是可選的,這意味著你需要明確決定哪些元件應該由 React 在客戶端渲染。

本頁將介紹客戶端元件 (Client Components) 的工作原理、它們的渲染方式,以及何時應該使用它們。

客戶端渲染的優勢

在客戶端進行渲染工作有幾個優勢,包括:

  • 互動性:客戶端元件 (Client Components) 可以使用狀態 (state)、效果 (effects) 和事件監聽器 (event listeners),這意味著它們能立即回應用戶操作並更新 UI。
  • 瀏覽器 API:客戶端元件 (Client Components) 能夠存取瀏覽器 API,例如 地理位置 API (geolocation)localStorage,讓你能為特定用例建構 UI。

在 Next.js 中使用客戶端元件 (Client Components)

要使用客戶端元件 (Client Components),你可以在檔案頂部、import 語句之前加入 React 的 "use client" 指令

"use client" 用於宣告伺服器元件 (Server Components) 和客戶端元件 (Client Components) 模組之間的邊界 (boundary)。這意味著在檔案中定義 "use client" 後,所有導入該檔案的模組(包括子元件)都會被視為客戶端套件的一部分。

'use client'

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  )
}

下方的圖表展示了巢狀元件結構。如果在 toggle.js 中使用 onClickuseState 但未定義 "use client" 指令,將會導致錯誤。這是因為預設情況下元件會在伺服器端渲染,而這些 API 在伺服器端不可用。透過在 toggle.js 中定義 "use client" 指令,你可以告訴 React 在客戶端渲染該元件及其子元件,因為這些 API 在客戶端是可用的。

Use Client Directive and Network Boundary

定義多個 use client 進入點

你可以在 React 元件樹中定義多個 "use client" 進入點。這讓你能將應用程式拆分為多個客戶端套件(或分支)。

然而,並非每個需要在客戶端渲染的元件都必須定義 "use client"。一旦定義了邊界 (boundary),所有導入該檔案中的子元件和模組都會被視為客戶端套件的一部分。

客戶端元件 (Client Components) 如何渲染?

在 Next.js 中,客戶端元件 (Client Components) 的渲染方式會根據請求是屬於完整頁面載入(首次訪問應用程式或由瀏覽器重新整理觸發的頁面重新載入)還是後續導航而有所不同。

完整頁面載入

為了優化初始頁面載入,Next.js 會使用 React 的 API 在伺服器端為客戶端元件 (Client Components) 和伺服器元件 (Server Components) 渲染靜態 HTML 預覽。這意味著,當用戶首次訪問你的應用程式時,他們會立即看到頁面內容,而無需等待客戶端下載、解析和執行客戶端元件 (Client Components) 的 JavaScript 套件。

在伺服器端:

  1. React 將伺服器元件 (Server Components) 渲染為一種特殊的資料格式,稱為 React 伺服器元件負載 (RSC Payload),其中包含對客戶端元件 (Client Components) 的引用。
  2. Next.js 使用 RSC Payload 和客戶端元件 (Client Components) 的 JavaScript 指令在伺服器端渲染路由的 HTML

然後,在客戶端:

  1. 使用 HTML 立即顯示路由的快速非互動式初始預覽。
  2. 使用 React 伺服器元件負載 (RSC Payload) 協調客戶端元件 (Client Components) 和伺服器元件 (Server Components) 的樹結構,並更新 DOM。
  3. 使用 JavaScript 指令對客戶端元件 (Client Components) 進行水合 (hydrate),使其 UI 具有互動性。

什麼是水合 (hydration)?

水合 (hydration) 是將事件監聽器附加到 DOM 的過程,目的是讓靜態 HTML 具有互動性。在底層,水合 (hydration) 是透過 React 的 hydrateRoot API 完成的。

後續導航

在後續導航中,客戶端元件 (Client Components) 會完全在客戶端渲染,而不使用伺服器渲染的 HTML。

這意味著客戶端元件 (Client Components) 的 JavaScript 套件會被下載並解析。一旦套件準備就緒,React 會使用 RSC Payload 協調客戶端元件 (Client Components) 和伺服器元件 (Server Components) 的樹結構,並更新 DOM。

返回伺服器環境

有時,在宣告了 "use client" 邊界 (boundary) 後,你可能會想返回伺服器環境。例如,你可能希望減少客戶端套件的大小、在伺服器端獲取資料,或使用僅在伺服器端可用的 API。

即使程式碼理論上位於客戶端元件 (Client Components) 內部,你仍然可以透過交錯使用客戶端元件 (Client Components)、伺服器元件 (Server Components) 和伺服器操作 (Server Actions) 來將程式碼保留在伺服器端。更多資訊請參閱組合模式 (Composition Patterns) 頁面。

On this page