Closed godmmt closed 2 months ago
在 Next.js 的 App Router 中,Server Components 和 Client Components 可以混合使用。
混合使用的注意事項:
props
的傳遞混合使用 Server Components 和 Client Components 時,傳遞 props
是一個需要特別注意的部分,因為伺服器與客戶端的運作環境不同。
以下是 props 傳遞時的主要注意事項:
props
string
、number
、array
、object
等。props
傳遞給子元件(包括 Client Components)。export default async function ServerComponent() {
const data = await fetchDataFromAPI();
return <ClientComponent data={data} />;
}
props
props
必須是可以序列化的。Date
物件、Map
、Set
等),這些資料類型無法在伺服器與客戶端之間傳遞。props
,Next.js 會拋出錯誤。// 這樣是行不通的,因為函數無法序列化
export default function ServerComponent() {
const myFunction = () => console.log('Hello');
return <ClientComponent onClick={myFunction} />;
}
// 改成這樣,傳遞可序列化的資料
export default function ServerComponent() {
const message = 'Hello';
return <ClientComponent message={message} />;
}
props
props
,因為它們全都在伺服器端運行,不受序列化限制。export default function ParentServerComponent() {
const data = { name: "John", age: 30 };
return <ChildServerComponent person={data} />;
}
function ChildServerComponent({ person }) {
return <div>{person.name}</div>;
}
props
的限制props
傳遞給 Client Components 時,需要確保傳遞的是基本的 JavaScript 值(如字串、數字、陣列、物件)。如果需要傳遞較複雜的資料類型,建議將其轉換為可序列化的格式(例如將 Date
物件轉換為 ISO 字串)。export default function ServerComponent() {
const date = new Date().toISOString(); // 確保可以序列化
return <ClientComponent dateString={date} />;
}
("use client");
export function ClientComponent({ dateString }) {
const date = new Date(dateString);
return <p>{date.toDateString()}</p>;
}
props
會增加 JavaScript bundle 大小,影響效能。props
傳遞給 Client Components,因為這些資料會暴露在瀏覽器中。在 Next.js App Router 中,Client Components 和 Server Components 各自有不同的用途和限制。具體來說,Client Components 可以使用許多 React 客戶端的功能,但這些功能無法在 Server Components 中使用。
以下是一些只能在 Client Components 使用,而不能在 Server Components 使用的功能:
useState
:用於管理元件內的本地狀態,會在客戶端運行。useEffect
:用於處理副作用,這些副作用只會在瀏覽器中執行,如訂閱、API 請求等。useContext
:用於讀取(access) React 的 context API,與狀態管理相關。useReducer
、useRef
:這些都是與客戶端元件狀態或 DOM 互動相關的 hooks,無法在伺服器端執行。onClick
、onChange
、onSubmit
等事件處理函數只在客戶端執行。這類事件函數涉及與 DOM 的互動,必須在瀏覽器中運行。props
傳遞,並作為事件處理邏輯,只能在 Client Components 使用,因為伺服器無法執行客戶端的 JavaScript 行為。window
、document
、localStorage
、sessionStorage
、navigator
等只能在客戶端執行,因為這些物件在伺服器端並不存在。document.getElementById
或 window.addEventListener
,只能在 Client Components 中執行。useEffect
中的 API 請求:雖然 Server Components 可以直接在伺服器端進行 API 請求(例如透過 fetch 來獲取資料),但需要在客戶端發起的動態 API 請求(例如在表單提交時調用 API)只能在 Client Components 中處理。import()
動態導入:這種導入方式在客戶端執行時使用,無法在伺服器端動態導入客戶端模組。useLayoutEffect
:這個 hook 在瀏覽器 DOM 加載後運行,用來計算佈局,不能在伺服器端使用,因為伺服器端無法讀取瀏覽器的 DOM。ReactDOM.createPortal
:用於將元件渲染到 DOM 節點的其他部分(例如 Modal 彈窗等),只能在客戶端使用。localStorage
、sessionStorage
或使用 cookie
(瀏覽器中的 client-side cookies)只能在 Client Components 中完成。雖然 Server Components 可以在伺服器端讀取或寫入 cookie,但這是在 HTTP 層面進行的,不是透過 JavaScript 操作的瀏覽器儲存。客戶端元件不能包裹伺服器元件,這是因為伺服器元件是在伺服器端執行並生成靜態 HTML,而客戶端元件是在客戶端執行的動態 JavaScript 元件。
具體原因如下:
在 Next.js App Router 中,客戶端元件不能包裹伺服器元件,只能是伺服器元件包裹客戶端元件。這是因為渲染流程是先由伺服器處理,再由客戶端補充互動功能。
'use client'
。getStaticProps
都需要移除。新增補充
0905: took 6 0906: took 2
Total time: 8
done.
文章位置: https://github.com/CAFECA-IO/KnowledgeManagement/blob/master/NextJs/app-router-vs-pages-router-in-next-js.md