Parent Component?Owner Component?是甚麼東西?

2025-02-121.19Front EndNextjsReactParent Component?Owner Component?是甚麼東西?

如果你有在寫 React / Next.js,Parent Component(父元件)這個詞你應該耳熟能詳吧。但你知道還有個叫做「Owner Component」的東西嗎?

這兩個聽起來很像,實際上差很多。尤其當你的應用越寫越大,效能越來越卡,就會開始在意「到底是誰在控制這顆元件」,而不只是「誰包住它」。


先講什麼是 Parent?

Parent 就是最簡單的那種「我在 JSX 裡包住你」的關係。

function ProfilePage() { return ( <div> <h2>個人資料</h2> <UserCard /> </div> ); }

這邊 ProfilePageUserCard 的 Parent,沒什麼問題,它直接把子元件放進自己的 render tree 裡。這樣的結構我們都很熟悉。


Owner 是什麼?有主控權的角色

Owner 指的是那個真的控制這顆元件的人,它決定要不要渲染它,決定它的 props 是什麼,甚至 props 怎麼變也都是它說了算。

我們來看個不一樣的例子:

function App() { const user = { name: "小明", age: 28 }; return ( <ProfilePage> <UserCard user={user} /> </ProfilePage> ); } function ProfilePage({ children }) { return ( <div> <h2>個人資料</h2> {children} </div> ); }

在這邊,App 才是 UserCard 的 Owner。它決定傳什麼 props,要不要顯示這顆元件。而 ProfilePage 只是個容器,包起來,但完全不碰 user 資料,也不知道你傳了什麼。

簡單講就是:

  • Parent:包住你,但不知道你幹嘛。

  • Owner:控制你,知道你幹嘛、讓你幹嘛。


為什麼要知道這個?因為 render 卡頓的時候很重要 !

當你的某個 Component 很愛 re-render,但它裡面其實什麼都沒改,那你就要開始懷疑是不是有誰在「牽連它」,讓它不小心也被 re-render 到。

這時候,把元件的 owner 角色切清楚就很有幫助。

比如這樣:

function App() { return ( <ProfileReRenderWrapper> <UserCard /> </ProfileReRenderWrapper > ); }
 

UserCard 是被包進去的,但它的資料沒有任何變動,單純只是顯示使用者資訊。那我們可以透過 children 把它插進去,而不要讓 ProfileReRenderWrapper 負責控制它的狀態。這樣 UserCard 就不會因為 ProfileReRenderWrapper 的狀態改變而跟著 re-render。


拉回到 Next.js App Router:Client / Server Component 的拆法

你如果用的是 Next.js 的 App Router(也就是那個 app/ 目錄),應該知道所有 Component 預設都是 Server Component。

但只要用了 useStateuseEffect 或有互動功能,就要加上 'use client'

然後問題就來了:

Client Component 不能直接 import Server Component。

 

Client Component 不能直接導入 Server Component,因為 Server Component 是在伺服器端執行的,它的內容已經在伺服器渲染完成後變成靜態 HTML,而 Client Component 則在瀏覽器端運行,需要參與 React 的渲染週期。

 

'use client' // 錯誤示範 import ServerComponent from './Server-Component' export default function ClientComponent() { const [count, setCount] = useState(0) return ( <> <button onClick={() => setCount(count + 1)}>{count}</button> <ServerComponent /> {/* 這裡會爆 */} </> ) }

那怎麼辦?這時候我們可以套用 Owner / Parent 的概念。

Client Component 不要當 Owner,它只要當 Parent。

把 Server Component 當作 children 傳進去就行:

'use client' import { useState } from 'react' export default function ClientComponent({ children }) { const [count, setCount] = useState(0) return ( <> <button onClick={() => setCount(count + 1)}>{count}</button> {children} </> ) }

然後在外面用的時候這樣寫:

import ClientComponent from './client-component' import ServerComponent from './server-component' export default function Page() { return ( <ClientComponent> <ServerComponent /> </ClientComponent> ) }

這樣就解啦。因為這時候 ClientComponent 不再是 ServerComponent 的 Owner,只是 Parent,渲染控制權還是在外層的 Server Component 上。


小結一下

搞懂誰是 Parent 誰是 Owner,不只是為了理解架構,還能讓你的效能優化更清楚。而且在 Next.js 的 Server / Client Component 限制下,這種分工超實用。

所以,下次遇到:

  • 為什麼這顆會一直 re-render?

  • 為什麼我不能 import 某個 Component?

  • 為什麼 children 傳進去就可以解?

想一下 Owner / Parent 誰是誰,你就會知道答案在哪。


如果你覺得這個觀念蠻酷但有點繞,也可以想成這樣:

Parent 是「你住哪」的概念,Owner 是「誰決定你住哪」的概念。

簡單粗暴,但很有用。

參考

https://julesblom.com/writing/parents-owners-data-flow

https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns