createRoot
可讓您建立一個根目錄,以便在瀏覽器 DOM 節點內顯示 React 元件。
const root = createRoot(domNode, options?)
參考
createRoot(domNode, options?)
呼叫 createRoot
建立一個 React 根目錄,以在瀏覽器 DOM 元素內顯示內容。
import { createRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = createRoot(domNode);
React 將會為 domNode
建立一個根目錄,並接管其中 DOM 的管理。建立根目錄後,您需要呼叫 root.render
以在其中顯示 React 元件
root.render(<App />);
完全使用 React 建立的應用程式通常只會針對其根元件呼叫一次 createRoot
。使用 React 建立頁面部分內容的頁面,可以根據需要使用多個不同的根目錄。
參數
-
domNode
:一個 DOM 元素。React 將會為此 DOM 元素建立一個根目錄,並允許您在根目錄上呼叫函式,例如render
來顯示渲染的 React 內容。 -
選用
options
:包含此 React 根目錄選項的物件。- 選用
onCaughtError
:當 React 在錯誤邊界中攔截到錯誤時呼叫的回呼函式。使用錯誤邊界攔截到的error
和包含componentStack
的errorInfo
物件呼叫。 - 選用
onUncaughtError
:當擲出錯誤且未被錯誤邊界攔截時呼叫的回呼函式。使用擲出的error
和包含componentStack
的errorInfo
物件呼叫。 - 選用
onRecoverableError
:當 React 自動從錯誤中復原時呼叫的回呼函式。使用 React 擲出的error
和包含componentStack
的errorInfo
物件呼叫。某些可復原的錯誤可能包含原始錯誤原因,作為error.cause
。 - 選用
identifierPrefix
:React 用於由useId
產生的 ID 的字串前綴。這在同個頁面使用多個根目錄時,有助於避免衝突。
- 選用
回傳值
createRoot
會回傳一個物件,包含兩個方法:render
和 unmount
。
注意事項
- 如果您的應用程式是伺服器端渲染的,則不支援使用
createRoot()
。請改用hydrateRoot()
。 - 您的應用程式中可能只會呼叫一次
createRoot
。如果您使用框架,它可能會幫您完成此呼叫。 - 當您想要在 DOM 樹中不同於組件子項的部分渲染 JSX(例如,模態框或工具提示)時,請使用
createPortal
,而不是createRoot
。
root.render(reactNode)
呼叫 root.render
將一段 JSX(「React 節點」)顯示到 React 根目錄的瀏覽器 DOM 節點中。
root.render(<App />);
React 將在 root
中顯示 <App />
,並接管其中 DOM 的管理。
參數
reactNode
:您想要顯示的 *React 節點*。這通常是一段 JSX,例如<App />
,但您也可以傳遞使用createElement()
建構的 React 元素、字串、數字、null
或undefined
。
回傳值
root.render
回傳 undefined
。
注意事項
-
第一次呼叫
root.render
時,React 會在將 React 組件渲染到 React 根目錄之前,清除其中所有現有的 HTML 內容。 -
如果您的根目錄的 DOM 節點包含伺服器或建置期間由 React 產生的 HTML,請改用
hydrateRoot()
,它會將事件處理程式附加到現有的 HTML。 -
如果您在同一個根節點上多次呼叫
render
,React 將會視需要更新 DOM 以反映您傳遞的最新 JSX。React 會藉由將其與先前渲染的樹狀結構「比對」來決定 DOM 的哪些部分可以重複使用,哪些需要重新建立。在同一個根節點上再次呼叫render
類似於在根組件上呼叫set
函式:React 會避免不必要的 DOM 更新。
root.unmount()
呼叫 root.unmount
可以銷毀 React 根節點內已渲染的樹狀結構。
root.unmount();
完全使用 React 建構的應用程式通常不會呼叫 root.unmount
。
當您的 React 根節點的 DOM 節點(或其任何祖先節點)可能被其他程式碼從 DOM 中移除時,這會很有用。例如,想像一個 jQuery 標籤面板,它會從 DOM 中移除非活動的標籤頁。如果一個標籤頁被移除,它裡面的所有內容(包括裡面的 React 根節點)也會從 DOM 中移除。在這種情況下,您需要透過呼叫 root.unmount
來告知 React「停止」管理已移除根節點的內容。否則,已移除根節點內的組件將不知道要清理並釋放全域資源,例如訂閱。
呼叫 root.unmount
將會卸載根節點中的所有組件,並將 React 與根 DOM 節點「分離」,包括移除樹狀結構中的任何事件處理程式或狀態。
參數
root.unmount
不接受任何參數。
回傳值
root.unmount
回傳 undefined
。
注意事項
-
呼叫
root.unmount
將會卸載樹狀結構中的所有組件,並將 React 與根 DOM 節點「分離」。 -
呼叫
root.unmount
後,您無法在同一個根節點上再次呼叫root.render
。嘗試在已卸載的根節點上呼叫root.render
將會拋出「無法更新已卸載的根節點」錯誤。但是,您可以在前一個根節點已被卸載後,為同一個 DOM 節點建立新的根節點。
用法
渲染完全使用 React 建構的應用程式
如果您的應用程式完全使用 React 建構,請為整個應用程式建立單一根節點。
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
通常,您只需要在啟動時執行一次此程式碼。它將會
- 找到您 HTML 中定義的 瀏覽器 DOM 節點。
- 在其中顯示應用程式的 React 組件。
import { createRoot } from 'react-dom/client'; import App from './App.js'; import './styles.css'; const root = createRoot(document.getElementById('root')); root.render(<App />);
如果您的應用程式完全使用 React 建構,您應該不需要建立任何其他根節點,也不需要再次呼叫 root.render
。
從現在開始,React 將會管理您整個應用程式的 DOM。要新增更多組件,請將它們嵌套在 App
組件內。當您需要更新 UI 時,每個組件都可以透過使用狀態來完成。當您需要在 DOM 節點之外顯示額外內容(例如模態框或工具提示)時,請使用入口網站來渲染它。
渲染部分使用 React 建置的頁面
如果你的頁面並非完全使用 React 建置,你可以多次呼叫 createRoot
來為每個由 React 管理的頂層 UI 建立一個根。你可以透過呼叫 root.render
在每個根中顯示不同的內容。
這裡,兩個不同的 React 元件被渲染到在 index.html
檔案中定義的兩個 DOM 節點中。
import './styles.css'; import { createRoot } from 'react-dom/client'; import { Comments, Navigation } from './Components.js'; const navDomNode = document.getElementById('navigation'); const navRoot = createRoot(navDomNode); navRoot.render(<Navigation />); const commentDomNode = document.getElementById('comments'); const commentRoot = createRoot(commentDomNode); commentRoot.render(<Comments />);
你也可以使用 document.createElement()
建立一個新的 DOM 節點,並手動將其新增到文件中。
const domNode = document.createElement('div');
const root = createRoot(domNode);
root.render(<Comment />);
document.body.appendChild(domNode); // You can add it anywhere in the document
要從 DOM 節點中移除 React 樹狀結構並清除它使用的所有資源,請呼叫 root.unmount
。
root.unmount();
如果你的 React 元件位於以其他框架編寫的應用程式中,這會很有用。
更新根元件
你可以在同一個根上多次呼叫 render
。只要元件樹狀結構與先前渲染的內容相符,React 就會保留狀態。請注意你可以如何在輸入框中輸入文字,這表示在本例中,每秒重複呼叫 render
的更新並非破壞性的。
import { createRoot } from 'react-dom/client'; import './styles.css'; import App from './App.js'; const root = createRoot(document.getElementById('root')); let i = 0; setInterval(() => { root.render(<App counter={i} />); i++; }, 1000);
多次呼叫 render
並不常見。通常,你的元件會更新狀態。
顯示未攔截錯誤的對話框
預設情況下,React 會將所有未攔截的錯誤記錄到控制台。要實作你自己的錯誤報告,你可以提供選用的 onUncaughtError
根選項。
import { createRoot } from 'react-dom/client';
const root = createRoot(
document.getElementById('root'),
{
onUncaughtError: (error, errorInfo) => {
console.error(
'Uncaught error',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);
onUncaughtError 選項是一個带有兩個參數的函式:
- 拋出的 error(錯誤)。
- 一個包含錯誤 errorInfo 物件,其中包含錯誤的 componentStack(元件堆疊)。
你可以使用 onUncaughtError
根選項來顯示錯誤對話框。
import { createRoot } from "react-dom/client"; import App from "./App.js"; import {reportUncaughtError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container, { onUncaughtError: (error, errorInfo) => { if (error.message !== 'Known error') { reportUncaughtError({ error, componentStack: errorInfo.componentStack }); } } }); root.render(<App />);
顯示錯誤邊界錯誤
預設情況下,React 會將錯誤邊界攔截的所有錯誤記錄到 console.error
。要覆蓋此行為,你可以提供選用的 onCaughtError
根選項來處理錯誤邊界攔截的錯誤。
import { createRoot } from 'react-dom/client';
const root = createRoot(
document.getElementById('root'),
{
onCaughtError: (error, errorInfo) => {
console.error(
'Caught error',
error,
errorInfo.componentStack
);
}
}
);
root.render(<App />);
onCaughtError 選項是一個带有兩個參數的函式:
- 邊界攔截的 error(錯誤)。
- 一個包含錯誤 errorInfo 物件,其中包含錯誤的 componentStack(元件堆疊)。
你可以使用 onCaughtError
根選項來顯示錯誤對話框或篩選記錄中已知的錯誤。
import { createRoot } from "react-dom/client"; import App from "./App.js"; import {reportCaughtError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container, { onCaughtError: (error, errorInfo) => { if (error.message !== 'Known error') { reportCaughtError({ error, componentStack: errorInfo.componentStack, }); } } }); root.render(<App />);
顯示可復原錯誤的對話框
React 可能會自動再次渲染元件,以嘗試從渲染中拋出的錯誤中復原。如果成功,React 會將可復原的錯誤記錄到控制台以通知開發人員。要覆蓋此行為,你可以提供選用的 onRecoverableError
根選項。
import { createRoot } from 'react-dom/client';
const root = createRoot(
document.getElementById('root'),
{
onRecoverableError: (error, errorInfo) => {
console.error(
'Recoverable error',
error,
error.cause,
errorInfo.componentStack,
);
}
}
);
root.render(<App />);
onRecoverableError 選項是一個带有兩個參數的函式:
- React 拋出的 error(錯誤)。某些錯誤可能包含原始原因,如 error.cause。
- 一個包含錯誤 errorInfo 物件,其中包含錯誤的 componentStack(元件堆疊)。
你可以使用 onRecoverableError
根選項來顯示錯誤對話框。
import { createRoot } from "react-dom/client"; import App from "./App.js"; import {reportRecoverableError} from "./reportError"; import "./styles.css"; const container = document.getElementById("root"); const root = createRoot(container, { onRecoverableError: (error, errorInfo) => { reportRecoverableError({ error, cause: error.cause, componentStack: errorInfo.componentStack, }); } }); root.render(<App />);
疑難排解
我已經建立了一個根節點,但沒有任何顯示
請確認您沒有忘記將您的應用程式實際渲染到根節點中
import { createRoot } from 'react-dom/client';
import App from './App.js';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
在您執行該操作之前,不會顯示任何內容。
我收到一個錯誤:「您傳遞了第二個參數給 root.render」
一個常見的錯誤是將 createRoot
的選項傳遞給 root.render(...)
要修復此問題,請將根選項傳遞給 createRoot(...)
,而不是 root.render(...)
// 🚩 Wrong: root.render only takes one argument.
root.render(App, {onUncaughtError});
// ✅ Correct: pass options to createRoot.
const root = createRoot(container, {onUncaughtError});
root.render(<App />);
我收到一個錯誤:「目標容器不是 DOM 元素」
這個錯誤表示您傳遞給 createRoot
的任何內容都不是 DOM 節點。
如果您不確定發生了什麼事,請嘗試記錄它
const domNode = document.getElementById('root');
console.log(domNode); // ???
const root = createRoot(domNode);
root.render(<App />);
例如,如果 domNode
是 null
,則表示 getElementById
傳回了 null
。如果在您呼叫時文件中沒有具有指定 ID 的節點,就會發生這種情況。可能原因有幾個
- 您要查找的 ID 可能與您在 HTML 檔案中使用的 ID 不同。檢查是否有錯字!
- 您的套件的
<script>
標籤無法「看到」HTML 中在其之後出現的任何 DOM 節點。
導致此錯誤的另一個常見原因是編寫 createRoot(<App />)
而不是 createRoot(domNode)
。
我收到一個錯誤:「函數不是有效的 React 子項。」
這個錯誤表示您傳遞給 root.render
的任何內容都不是 React 元件。
如果您使用 Component
而不是 <Component />
呼叫 root.render
,就可能會發生這種情況
// 🚩 Wrong: App is a function, not a Component.
root.render(App);
// ✅ Correct: <App /> is a component.
root.render(<App />);
或者,如果您將函數傳遞給 root.render
,而不是呼叫它的結果
// 🚩 Wrong: createApp is a function, not a component.
root.render(createApp);
// ✅ Correct: call createApp to return a component.
root.render(createApp());
我的伺服器渲染 HTML 會從頭開始重新建立
如果您的應用程式是伺服器渲染的,並且包含 React 產生的初始 HTML,您可能會注意到建立根節點並呼叫 root.render
會刪除所有 HTML,然後從頭開始重新建立所有 DOM 節點。這可能會比較慢,會重設焦點和捲動位置,並且可能會遺失其他使用者輸入。
伺服器渲染的應用程式必須使用 hydrateRoot
而不是 createRoot
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(
document.getElementById('root'),
<App />
);
請注意,它的 API 不同。特別是,通常不會再有 root.render
呼叫。