createRoot
允许你创建一个根以在浏览器 DOM 节点内显示 React 组件。
¥createRoot
lets you create a root to display React components inside a browser DOM node.
const root = createRoot(domNode, options?)
参考
¥Reference
createRoot(domNode, options?)
调用 createRoot
创建一个 React 根,用于在浏览器 DOM 元素中显示内容。
¥Call createRoot
to create a React root for displaying content inside a browser DOM element.
import { createRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = createRoot(domNode);
React 将为 domNode
创建一个根,并接管管理其中的 DOM。创建根后,你需要调用 root.render
以在其中显示一个 React 组件:
¥React will create a root for the domNode
, and take over managing the DOM inside it. After you’ve created a root, you need to call root.render
to display a React component inside of it:
root.render(<App />);
完全使用 React 构建的应用通常只有一个 createRoot
调用其根组件。将 React 的 “sprinkles” 用于页面的某些部分的页面可以根据需要具有尽可能多的单独根。
¥An app fully built with React will usually only have one createRoot
call for its root component. A page that uses “sprinkles” of React for parts of the page may have as many separate roots as needed.
参数
¥Parameters
-
domNode
:DOM 元素。 React 将为此 DOM 元素创建一个根,并允许你调用根上的函数,例如render
以显示渲染的 React 内容。¥
domNode
: A DOM element. React will create a root for this DOM element and allow you to call functions on the root, such asrender
to display rendered React content. -
可选
options
:具有此 React 根选项的对象。¥optional
options
: An object with options for this React root.
可选 onCaughtError
:当 React 在错误边界中捕获错误时调用的回调。使用被错误边界捕获的 error
和包含 componentStack
的 errorInfo
对象调用。*
¥optional onCaughtError
: Callback called when React catches an error in an Error Boundary. Called with the error
caught by the Error Boundary, and an errorInfo
object containing the componentStack
.
可选 onUncaughtError
:当抛出错误但未被错误边界捕获时调用的回调。使用抛出的 error
和包含 componentStack
的 errorInfo
对象进行调用。
¥optional onUncaughtError
: Callback called when an error is thrown and not caught by an Error Boundary. Called with the error
that was thrown, and an errorInfo
object containing the componentStack
.
-
可选
onRecoverableError
:当 React 自动从错误中恢复时调用的回调。使用 React 抛出的error
和包含componentStack
的errorInfo
对象调用。某些可恢复错误可能将原始错误原因包括为error.cause
。¥optional
onRecoverableError
: Callback called when React automatically recovers from errors. Called with anerror
React throws, and anerrorInfo
object containing thecomponentStack
. Some recoverable errors may include the original error cause aserror.cause
. -
可选
identifierPrefix
:React 用于useId
。 生成的 ID 的字符串前缀 有助于避免在同一页面上使用多个根时发生冲突。¥optional
identifierPrefix
: A string prefix React uses for IDs generated byuseId
. Useful to avoid conflicts when using multiple roots on the same page.
返回
¥Returns
createRoot
返回一个有两个方法的对象:render
和 unmount
。
¥createRoot
returns an object with two methods: render
and unmount
.
注意事项
¥Caveats
-
如果你的应用是服务器渲染的,则不支持使用
createRoot()
。请改用hydrateRoot()
。¥If your app is server-rendered, using
createRoot()
is not supported. UsehydrateRoot()
instead. -
你的应用中可能只有一个
createRoot
调用。如果你使用框架,它可能会为你执行此调用。¥You’ll likely have only one
createRoot
call in your app. If you use a framework, it might do this call for you. -
当你想在 DOM 树的不同部分渲染一段 JSX 时,它不是你的组件的子级(例如,模态或工具提示),请使用
createPortal
而不是createRoot
。¥When you want to render a piece of JSX in a different part of the DOM tree that isn’t a child of your component (for example, a modal or a tooltip), use
createPortal
instead ofcreateRoot
.
root.render(reactNode)
调用 root.render
将 JSX (“React 节点”) 的一部分显示到 React root 的浏览器 DOM 节点中。
¥Call root.render
to display a piece of JSX (“React node”) into the React root’s browser DOM node.
root.render(<App />);
React 将在 root
中显示 <App />
,并接管管理其中的 DOM。
¥React will display <App />
in the root
, and take over managing the DOM inside it.
参数
¥Parameters
-
reactNode
:你要显示的 React 节点。这通常是一段 JSX,如<App />
,但你也可以传递一个由createElement()
、字符串、数字、null
或undefined
构造的 React 元素。¥
reactNode
: A React node that you want to display. This will usually be a piece of JSX like<App />
, but you can also pass a React element constructed withcreateElement()
, a string, a number,null
, orundefined
.
返回
¥Returns
root.render
返回 undefined
。
¥root.render
returns undefined
.
注意事项
¥Caveats
-
第一次调用
root.render
时,React 将清除 React 根目录中所有现有的 HTML 内容,然后再将 React 组件渲染到其中。¥The first time you call
root.render
, React will clear all the existing HTML content inside the React root before rendering the React component into it. -
如果你的根节点的 DOM 节点包含 React 在服务器上或构建期间生成的 HTML,请改用
hydrateRoot()
,它将事件处理程序附加到现有 HTML。¥If your root’s DOM node contains HTML generated by React on the server or during the build, use
hydrateRoot()
instead, which attaches the event handlers to the existing HTML. -
如果你在同一个根上多次调用
render
,React 将根据需要更新 DOM 以反映你传递的最新 JSX。React 将决定 DOM 的哪些部分可以重用,哪些需要由 “匹配它” 使用之前渲染的树重新创建。再次在同一个根上调用render
类似于在根组件上调用set
函数:React 避免了不必要的 DOM 更新。¥If you call
render
on the same root more than once, React will update the DOM as necessary to reflect the latest JSX you passed. React will decide which parts of the DOM can be reused and which need to be recreated by “matching it up” with the previously rendered tree. Callingrender
on the same root again is similar to calling theset
function on the root component: React avoids unnecessary DOM updates.
root.unmount()
调用 root.unmount
以销毁 React 根内的渲染树。
¥Call root.unmount
to destroy a rendered tree inside a React root.
root.unmount();
完全使用 React 构建的应用通常不会调用 root.unmount
。
¥An app fully built with React will usually not have any calls to root.unmount
.
如果你的 React 根的 DOM 节点(或其任何祖级节点)可能被其他代码从 DOM 中删除,这将非常有用。例如,假设一个 jQuery 选项卡面板从 DOM 中删除非活动选项卡。如果一个选项卡被删除,其中的所有内容(包括里面的 React 根)也会从 DOM 中删除。在这种情况下,你需要通过调用 root.unmount
告诉 React “stop” 管理删除的根目录的内容。否则,被删除的根内的组件将不知道清理和释放订阅等全局资源。
¥This is mostly useful if your React root’s DOM node (or any of its ancestors) may get removed from the DOM by some other code. For example, imagine a jQuery tab panel that removes inactive tabs from the DOM. If a tab gets removed, everything inside it (including the React roots inside) would get removed from the DOM as well. In that case, you need to tell React to “stop” managing the removed root’s content by calling root.unmount
. Otherwise, the components inside the removed root won’t know to clean up and free up global resources like subscriptions.
调用 root.unmount
将从根 DOM 节点卸载根中的所有组件和 “detach” React,包括删除树中的任何事件处理程序或状态。
¥Calling root.unmount
will unmount all the components in the root and “detach” React from the root DOM node, including removing any event handlers or state in the tree.
参数
¥Parameters
root.unmount
没有参数。
¥root.unmount
does not accept any parameters.
返回
¥Returns
root.unmount
返回 undefined
。
¥root.unmount
returns undefined
.
注意事项
¥Caveats
-
调用
root.unmount
将从根 DOM 节点卸载树中的所有组件和 “detach” React。¥Calling
root.unmount
will unmount all the components in the tree and “detach” React from the root DOM node. -
一旦你调用
root.unmount
,你就不能在同一个根上再次调用root.render
。尝试在未挂载的根上调用root.render
将引发 “无法更新卸载的根目录” 错误。但是,你可以在卸载该节点的先前根之后为同一 DOM 节点创建一个新根。¥Once you call
root.unmount
you cannot callroot.render
again on the same root. Attempting to callroot.render
on an unmounted root will throw a “Cannot update an unmounted root” error. However, you can create a new root for the same DOM node after the previous root for that node has been unmounted.
用法
¥Usage
渲染完全用 React 构建的应用
¥Rendering an app fully built with React
如果你的应用完全使用 React 构建,请为你的整个应用创建一个根目录。
¥If your app is fully built with React, create a single root for your entire app.
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
通常,你只需要在启动时运行此代码一次。它会:
¥Usually, you only need to run this code once at startup. It will:
-
找到在你的 HTML 中定义的 浏览器 DOM 节点。
¥Find the browser DOM node defined in your HTML.
-
在内部显示你的应用的 React 组件。
¥Display the React component for your app inside.
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
。
¥If your app is fully built with React, you shouldn’t need to create any more roots, or to call root.render
again.
从这一点开始,React 将管理整个应用的 DOM。要添加更多组件,将它们嵌套在 App
组件中。 当你需要更新 UI 时,你的每个组件都可以通过 使用状态。 执行此操作 当你需要在 DOM 节点外部显示额外内容(如模式或工具提示)时,用门户渲染它。
¥From this point on, React will manage the DOM of your entire app. To add more components, nest them inside the App
component. When you need to update the UI, each of your components can do this by using state. When you need to display extra content like a modal or a tooltip outside the DOM node, render it with a portal.
渲染部分使用 React 构建的页面
¥Rendering a page partially built with React
如果你的页面 不是完全用 React 构建的,你可以多次调用 createRoot
来为 React 管理的每个顶层 UI 片段创建一个根。可以通过调用 root.render
. 在每个根中显示不同的内容
¥If your page isn’t fully built with React, you can call createRoot
multiple times to create a root for each top-level piece of UI managed by React. You can display different content in each root by calling root.render
.
在这里,两个不同的 React 组件被渲染到 index.html
文件中定义的两个 DOM 节点中:
¥Here, two different React components are rendered into two DOM nodes defined in the index.html
file:
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 节点,然后手动将其添加到文档中。
¥You could also create a new DOM node with document.createElement()
and add it to the document manually.
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
.
¥To remove the React tree from the DOM node and clean up all the resources used by it, call root.unmount
.
root.unmount();
如果你的 React 组件位于用不同框架编写的应用中,这将非常有用。
¥This is mostly useful if your React components are inside an app written in a different framework.
更新根组件
¥Updating a root component
你可以在同一个根上多次调用 render
。只要组件树结构与之前渲染的内容相匹配,React 就会 保持状态。 通知你如何键入输入,这意味着在这个例子中每秒重复 render
调用的更新不是破坏性的:
¥You can call render
more than once on the same root. As long as the component tree structure matches up with what was previously rendered, React will preserve the state. Notice how you can type in the input, which means that the updates from repeated render
calls every second in this example are not destructive:
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
并不常见。通常,你的组件将改为 更新状态。
¥It is uncommon to call render
multiple times. Usually, your components will update state instead.
显示未捕获错误的对话框
¥Show a dialog for uncaught errors
默认情况下,React 会将所有未捕获的错误记录到控制台。要实现你自己的错误报告,你可以提供可选的 onUncaughtError
根选项:
¥By default, React will log all uncaught errors to the console. To implement your own error reporting, you can provide the optional onUncaughtError
root option:
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 选项是一个使用两个参数调用的函数:
¥The onUncaughtError option is a function called with two arguments:
-
抛出的 error。
¥The error that was thrown.
-
包含错误的 componentStack 的 errorInfo 对象。
¥An errorInfo object that contains the componentStack of the error.
你可以使用 onUncaughtError
根选项显示错误对话框:
¥You can use the onUncaughtError
root option to display error dialogs:
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 />);
显示错误边界错误
¥Displaying Error Boundary errors
默认情况下,React 会将错误边界捕获的所有错误记录到 console.error
。要覆盖此行为,你可以提供可选的 onCaughtError
根选项来处理 错误边界 捕获的错误:
¥By default, React will log all errors caught by an Error Boundary to console.error
. To override this behavior, you can provide the optional onCaughtError
root option to handle errors caught by an Error Boundary:
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 选项是一个使用两个参数调用的函数:
¥The onCaughtError option is a function called with two arguments:
-
被边界捕获的 error。
¥The error that was caught by the boundary.
-
包含错误的 componentStack 的 errorInfo 对象。
¥An errorInfo object that contains the componentStack of the error.
你可以使用 onCaughtError
根选项显示错误对话框或从日志中过滤已知错误:
¥You can use the onCaughtError
root option to display error dialogs or filter known errors from logging:
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 />);
显示可恢复错误的对话框
¥Displaying a dialog for recoverable errors
React 可能会自动第二次渲染组件,以尝试从渲染中抛出的错误中恢复。如果成功,React 会将可恢复错误记录到控制台以通知开发者。要覆盖此行为,你可以提供可选的 onRecoverableError
根选项:
¥React may automatically render a component a second time to attempt to recover from an error thrown in render. If successful, React will log a recoverable error to the console to notify the developer. To override this behavior, you can provide the optional onRecoverableError
root option:
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 选项是一个使用两个参数调用的函数:
¥The onRecoverableError option is a function called with two arguments:
-
React 抛出的 error。某些错误可能将原始原因包括为 error.cause。
¥The error that React throws. Some errors may include the original cause as error.cause.
-
包含错误的 componentStack 的 errorInfo 对象。
¥An errorInfo object that contains the componentStack of the error.
你可以使用 onRecoverableError
根选项显示错误对话框:
¥You can use the onRecoverableError
root option to display error dialogs:
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 />);
故障排除
¥Troubleshooting
我已经创建了一个根,但没有显示任何内容
¥I’ve created a root, but nothing is displayed
确保你没有忘记实际将你的应用渲染到根目录中:
¥Make sure you haven’t forgotten to actually render your app into the root:
import { createRoot } from 'react-dom/client';
import App from './App.js';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
在你这样做之前,不会显示任何内容。
¥Until you do that, nothing is displayed.
我收到错误:“你向 root.render 传递了第二个参数”
¥I’m getting an error: “You passed a second argument to root.render”
一个常见的错误是将 createRoot
的选项传递给 root.render(...)
:
¥A common mistake is to pass the options for createRoot
to root.render(...)
:
要修复此问题,请将根选项传递给 createRoot(...)
,而不是 root.render(...)
:
¥To fix, pass the root options to createRoot(...)
, not 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 元素”
¥I’m getting an error: “Target container is not a DOM element”
此错误意味着你传递给 createRoot
的任何内容都不是 DOM 节点。
¥This error means that whatever you’re passing to createRoot
is not a DOM node.
如果你不确定发生了什么,请尝试记录它:
¥If you’re not sure what’s happening, try logging it:
const domNode = document.getElementById('root');
console.log(domNode); // ???
const root = createRoot(domNode);
root.render(<App />);
例如,如果 domNode
是 null
,则表示 getElementById
返回了 null
。如果在你调用时文档中没有具有给定 ID 的节点,则会发生这种情况。可能有以下几个原因:
¥For example, if domNode
is null
, it means that getElementById
returned null
. This will happen if there is no node in the document with the given ID at the time of your call. There may be a few reasons for it:
-
你要查找的 ID 可能与你在 HTML 文件中使用的 ID 不同。检查错别字!
¥The ID you’re looking for might differ from the ID you used in the HTML file. Check for typos!
-
你的 bundle 的
<script>
标签不能 “看到” 在 HTML 中出现在它之后的任何 DOM 节点。¥Your bundle’s
<script>
tag cannot “see” any DOM nodes that appear after it in the HTML.
获得此错误的另一种常见方法是写 createRoot(<App />)
而不是 createRoot(domNode)
。
¥Another common way to get this error is to write createRoot(<App />)
instead of createRoot(domNode)
.
我收到错误:“函数作为 React 子项无效。”
¥I’m getting an error: “Functions are not valid as a React child.”
这个错误意味着你传递给 root.render
的任何东西都不是 React 组件。
¥This error means that whatever you’re passing to root.render
is not a React component.
如果你使用 Component
而不是 <Component />
调用 root.render
,则可能会发生这种情况:
¥This may happen if you call root.render
with Component
instead of <Component />
:
// 🚩 Wrong: App is a function, not a Component.
root.render(App);
// ✅ Correct: <App /> is a component.
root.render(<App />);
或者,如果你将一个函数传递给 root.render
,而不是调用它的结果:
¥Or if you pass a function to root.render
, instead of the result of calling it:
// 🚩 Wrong: createApp is a function, not a component.
root.render(createApp);
// ✅ Correct: call createApp to return a component.
root.render(createApp());
我的服务器渲染的 HTML 从头开始重新创建
¥My server-rendered HTML gets re-created from scratch
如果你的应用是服务器渲染的并且包含由 React 生成的初始 HTML,你可能会注意到创建根并调用 root.render
会删除所有 HTML,然后从头开始重新创建所有 DOM 节点。这可能会更慢,重置焦点和滚动位置,并且可能会丢失其他用户输入。
¥If your app is server-rendered and includes the initial HTML generated by React, you might notice that creating a root and calling root.render
deletes all that HTML, and then re-creates all the DOM nodes from scratch. This can be slower, resets focus and scroll positions, and may lose other user input.
服务器渲染的应用必须使用 hydrateRoot
而不是 createRoot
:
¥Server-rendered apps must use hydrateRoot
instead of createRoot
:
import { hydrateRoot } from 'react-dom/client';
import App from './App.js';
hydrateRoot(
document.getElementById('root'),
<App />
);
请注意,它的 API 是不同的。特别是,通常不会再有 root.render
调用。
¥Note that its API is different. In particular, usually there will be no further root.render
call.