diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index aea29797a5..e02faccf52 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -1,10 +1,12 @@ --- title: hydrateRoot +translators: + - childrentime --- -`hydrateRoot` lets you display React components inside a browser DOM node whose HTML content was previously generated by [`react-dom/server`.](/reference/react-dom/server) +`hydrateRoot` 函数允许你在先前由 [`react-dom/server`](/reference/react-dom/server) 生成的浏览器 HTML DOM 节点中展示 React 组件。 ```js const root = hydrateRoot(domNode, reactNode, options?) @@ -16,11 +18,11 @@ const root = hydrateRoot(domNode, reactNode, options?) --- -## Reference {/*reference*/} +## 参考 {/*reference*/} ### `hydrateRoot(domNode, reactNode, options?)` {/*hydrateroot*/} -Call `hydrateRoot` to “attach” React to existing HTML that was already rendered by React in a server environment. +用 `hydrateRoot` 函数将 React 连接到由 React 在服务端环境中渲染的现有 HTML 中。 ```js import { hydrateRoot } from 'react-dom/client'; @@ -29,99 +31,95 @@ const domNode = document.getElementById('root'); const root = hydrateRoot(domNode, reactNode); ``` -React will attach to the HTML that exists inside the `domNode`, and take over managing the DOM inside it. An app fully built with React will usually only have one `hydrateRoot` call with its root component. +React 将会连接到内部有 `domNode` 的 HTML 上,然后接管其中的 `domNode`。一个完全由 React 构建的应用只会在其根组件中调用一次 `hydrateRoot` 方法。 -[See more examples below.](#usage) +[请参见下面更多示例](#usage)。 -#### Parameters {/*parameters*/} +#### 参数 {/*parameters*/} -* `domNode`: A [DOM element](https://developer.mozilla.org/zh-CN/docs/Web/API/Element) that was rendered as the root element on the server. +* `domNode`:一个在服务器端渲染时呈现为根元素的 [DOM 元素](https://developer.mozilla.org/zh-CN/docs/Web/API/Element)。 -* `reactNode`: The "React node" used to render the existing HTML. This will usually be a piece of JSX like `` which was rendered with a `ReactDOM Server` method such as `renderToPipeableStream()`. +* `reactNode`:用于渲染已存在 HTML 的“React 节点”。这个节点通常是一些类似于 `` 的 JSX,它会在 `ReactDOM Server` 端使用类似于 `renderToPipeableStream()` 的方法进行渲染。 -* **optional** `options`: An object with options for this React root. +* **可选** `options`:一个包含此 React 根元素选项的对象。 - * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. - * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as used on the server. + * **可选** `onRecoverableError`:当 React 自动从错误中恢复时调用的回调函数。 + * **可选** `identifierPrefix`:字符串前缀,用于标识由 [`useId`](/reference/react/useId) 生成的 ID ,可以避免在同一页面上使用多个 React 根元素时出现冲突。必须与服务端使用的前缀相同。 +#### 返回值 {/*returns*/} -#### Returns {/*returns*/} +`hydrateRoot` 返回一个包含两个方法的对象 [`render`](#root-render) 和 [`unmount`](#root-unmount)。 -`hydrateRoot` returns an object with two methods: [`render`](#root-render) and [`unmount`.](#root-unmount) +#### 警告 {/*caveats*/} -#### Caveats {/*caveats*/} - -* `hydrateRoot()` expects the rendered content to be identical with the server-rendered content. You should treat mismatches as bugs and fix them. -* In development mode, React warns about mismatches during hydration. There are no guarantees that attribute differences will be patched up in case of mismatches. This is important for performance reasons because in most apps, mismatches are rare, and so validating all markup would be prohibitively expensive. -* You'll likely have only one `hydrateRoot` call in your app. If you use a framework, it might do this call for you. -* If your app is client-rendered with no HTML rendered already, using `hydrateRoot()` is not supported. Use [`createRoot()`](/reference/react-dom/client/createRoot) instead. +* `hydrateRoot()` 期望渲染内容与服务端渲染的内容完全相同。你应该将不匹配视为错误并进行修复。 +* 在开发模式下,React 会在 hydrate 期间发出不匹配警告。在不匹配的情况下,不能保证内容差异会被修补。出于性能原因,这很重要,因为在大多数应用程序中,不匹配很少见,因此验证所有标记将是昂贵而不可行的。 +* 你的应用程序可能只有一个 `hydrateRoot()` 函数调用。如果你使用框架,则可能会为你完成此调用。 +* 如果你的应用程序是客户端渲染,并且没有已渲染好的 HTML,则不支持使用 `hydrateRoot()`。请改用 [`createRoot()`](/reference/react-dom/client/createRoot)。 --- ### `root.render(reactNode)` {/*root-render*/} -Call `root.render` to update a React component inside a hydrated React root for a browser DOM element. +使用 `root.render` 更新一个 hydrate 根组件中的 React 组件来渲染浏览器端 DOM 元素。 ```js root.render(); ``` -React will update `` in the hydrated `root`. - -[See more examples below.](#usage) +React 将会在 hydrate `root` 中更新 ``。 -#### Parameters {/*root-render-parameters*/} +[参见下面更多示例](#usage)。 -* `reactNode`: A "React node" that you want to update. This will usually be a piece of JSX like ``, but you can also pass a React element constructed with [`createElement()`](/reference/react/createElement), a string, a number, `null`, or `undefined`. +#### 参数 {/*root-render-parameters*/} +* `reactNode`:你想要更新的 "React 节点"。通常这会是一段JSX代码,例如 ``,但你也可以传递一个通过 [`createElement()`](/reference/react/createElement) 创建的 React 元素,一个字符串,一个数字,`null` 值 或者 `undefined` 值。 -#### Returns {/*root-render-returns*/} +#### 返回值 {/*root-render-returns*/} -`root.render` returns `undefined`. +`root.render` 返回 `undefined` 值。 -#### Caveats {/*root-render-caveats*/} +#### 警告 {/*root-render-caveats*/} -* If you call `root.render` before the root has finished hydrating, React will clear the existing server-rendered HTML content and switch the entire root to client rendering. +* 如果你在根节点还没有完成 hydrate 的情况下调用了 `root.render`,React 将清除现有的服务端渲染 HTML 内容,并将整个根节点切换到客户端渲染。 --- ### `root.unmount()` {/*root-unmount*/} -Call `root.unmount` to destroy a rendered tree inside a React root. +调用 `root.unmount` 来销毁 React 根节点内的渲染树。 ```js root.unmount(); ``` -An app fully built with React will usually not have any calls to `root.unmount`. - -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. 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 clean up and free up resources like subscriptions. - -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. +完全使用 React 构建的应用通常不会有任何调用 `root.unmount` 的情况。 +这主要适用于 React 根节点的 DOM 节点(或其任何祖先节点)可能会被其他代码从 DOM 中移除的情况。例如,想象一下一个 jQuery 标签面板,它会将非活动标签从 DOM 中移除。如果一个标签被移除,其内部的所有内容(包括其中的 React 根节点)也将从 DOM 中移除。你需要调用 `root.unmount` 来告诉 React “停止”管理已移除根节点的内容。否则,已移除根节点内的组件将无法清理和释放已使用的资源,例如订阅。 -#### Parameters {/*root-unmount-parameters*/} +调用 `root.unmount` 将卸载根节点中的所有组件,并“分离” React 与根 DOM 节点之间的连接,包括删除树中的任何事件处理程序或状态。 -`root.unmount` does not accept any parameters. +#### 参数 {/*root-unmount-parameters*/} +`root.unmount` 不接受任何参数。 -#### Returns {/*root-unmount-returns*/} +#### 返回值 {/*root-unmount-returns*/} -`render` returns `null`. +`render` 返回 `null` 值。 -#### Caveats {/*root-unmount-caveats*/} +#### 警告 {/*root-unmount-caveats*/} -* Calling `root.unmount` will unmount all the components in the tree and "detach" React from the root DOM node. +* 调用 `root.unmount` 将卸载树中的所有组件,并“分离” React 与根 DOM 节点之间的连接。 -* Once you call `root.unmount` you cannot call `root.render` again on the root. Attempting to call `root.render` on an unmounted root will throw a "Cannot update an unmounted root" error. +* 一旦你调用 `root.unmount`,就不能再在根节点上调用 `root.render`。在未挂载的根节点上尝试调用 `root.render` 将抛出“不能更新未挂载的根节点”的错误。 --- -## Usage {/*usage*/} +## 用法 {/*usage*/} -### Hydrating server-rendered HTML {/*hydrating-server-rendered-html*/} +### hydrate 服务端渲染的 HTML {/*hydrating-server-rendered-html*/} -If your app's HTML was generated by [`react-dom/server`](/reference/react-dom/client/createRoot), you need to *hydrate* it on the client. +如果你的应用程序的 HTML 是由 [`react-dom/server`](/reference/react-dom/client/createRoot) 生成的,你需要在客户端上进行 **hydrate**。 ```js [[1, 3, "document.getElementById('root')"], [2, 3, ""]] import { hydrateRoot } from 'react-dom/client'; @@ -129,16 +127,16 @@ import { hydrateRoot } from 'react-dom/client'; hydrateRoot(document.getElementById('root'), ); ``` -This will hydrate the server HTML inside the browser DOM node with the React component for your app. Usually, you will do it once at startup. If you use a framework, it might do this behind the scenes for you. +对于你的应用程序来说,这将 hydrate 你的服务端 HTML 来复苏里面的 浏览器 DOM 节点React 组件。通常,你只需要在启动时执行一次。如果你使用框架,则可能会自动在幕后执行此操作。 -To hydrate your app, React will "attach" your components' logic to the initial generated HTML from the server. Hydration turns the initial HTML snapshot from the server into a fully interactive app that runs in the browser. +为了进行 hydrate,React 将把你的组件逻辑连接到服务器上生成的初始 HTML 中。hydrate 可以将来自服务器的初始 HTML 快照转换为在浏览器中运行的完全可交互应用。 ```html public/index.html

Hello, world!

``` @@ -178,30 +176,30 @@ function Counter() {
-You shouldn't need to call `hydrateRoot` again or to call it in more places. From this point on, React will be managing the DOM of your application. To update the UI, your components will [use state](/reference/react/useState) instead. +你不需要再次调用 `hydrateRoot` 或者在其他地方调用它。从现在开始,React 将管理你的应用程序的 DOM。想要更新 UI 请使用 [useState](/reference/react/useState) 替代。 -The React tree you pass to `hydrateRoot` needs to produce **the same output** as it did on the server. +传递给 `hydrateRoot` 的 React 树必须生成与服务端 **相同的输出**。 -This is important for the user experience. The user will spend some time looking at the server-generated HTML before your JavaScript code loads. Server rendering creates an illusion that the app loads faster by showing the HTML snapshot of its output. Suddenly showing different content breaks that illusion. This is why the server render output must match the initial render output on the client. +这对于用户体验非常重要。用户会在你的 JavaScript 代码加载前花费一些时间来查看服务端生成的 HTML。服务端渲染通过显示应用输出的 HTML 快照来产生了应用程序加速加载的错觉。突然出现不同的内容会破坏这种错觉。这就是为什么服务端渲染输出必须与客户端初始渲染输出匹配。 -The most common causes leading to hydration errors include: +导致 hydrate 错误的最常见原因包括: -* Extra whitespace (like newlines) around the React-generated HTML inside the root node. -* Using checks like `typeof window !== 'undefined'` in your rendering logic. -* Using browser-only APIs like [`window.matchMedia`](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/matchMedia) in your rendering logic. -* Rendering different data on the server and the client. +* 根节点 React 生成的 HTML 周围存在额外的空白符(如换行符)。 +* 在渲染逻辑中使用 `typeof window !== 'undefined'` 这样的判断。 +* 在渲染逻辑中使用仅限于浏览器端的 API,例如 [`window.matchMedia`](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/matchMedia)。 +* 在服务器和客户端渲染不同的数据。 -React recovers from some hydration errors, but **you must fix them like other bugs.** In the best case, they'll lead to a slowdown; in the worst case, event handlers can get attached to the wrong elements. +React 可以从一些 hydrate 错误中恢复,但 **你必须像处理其他 bug 一样修复它们**。在最好的情况下,它们会导致应用程序加载变慢;在最坏的情况下,事件处理程序可能会附加到错误的元素上。 --- -### Hydrating an entire document {/*hydrating-an-entire-document*/} +### hydrate 整个文档 {/*hydrating-an-entire-document*/} -Apps fully built with React can render the entire document as JSX, including the [``](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/html) tag: +完全使用 React 构建的应用程序可以将整个文档作为 JSX 渲染,包括 [``](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/html) 标签: ```js {3,13} function App() { @@ -221,7 +219,7 @@ function App() { } ``` -To hydrate the entire document, pass the [`document`](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/document) global as the first argument to `hydrateRoot`: +要对整个文档进行 hydrate 处理,将全局的 [`document`](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/document) 作为 `hydrateRoot` 的第一个参数传递: ```js {4} import { hydrateRoot } from 'react-dom/client'; @@ -232,18 +230,18 @@ hydrateRoot(document, ); --- -### Suppressing unavoidable hydration mismatch errors {/*suppressing-unavoidable-hydration-mismatch-errors*/} +### 抑制不可避免的 hydrate 处理不匹配错误 {/*suppressing-unavoidable-hydration-mismatch-errors*/} -If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the hydration mismatch warning. +如果一个单独元素属性或文本内容在服务器和客户端之间是不可避免地不同的(例如,时间戳),则可以抑制 hydrate 处理不匹配警告。 -To silence hydration warnings on an element, add `suppressHydrationWarning={true}`: +要消除对元素的 hydrate 处理警告,请添加 `suppressHydrationWarning={true}`: ```html public/index.html

Current Date: 01/01/2020

``` @@ -268,20 +266,20 @@ export default function App() {
-This only works one level deep, and is intended to be an escape hatch. Don’t overuse it. Unless it’s text content, React still won’t attempt to patch it up, so it may remain inconsistent until future updates. +此方法仅适用于当前层级,并且旨在作为一种应急方案。不要滥用它。除非是文本内容,否则 React 不会尝试修补它,因此可能会保持不一致,直到未来的更新来到。 --- -### Handling different client and server content {/*handling-different-client-and-server-content*/} +### 处理不同的客户端和服务端内容 {/*handling-different-client-and-server-content*/} -If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a [state variable](/reference/react/useState) like `isClient`, which you can set to `true` in an [Effect](/reference/react/useEffect): +如果你有意在服务器和客户端上呈现不同的内容,则可以进行两次渲染。在客户端上呈现不同内容的组件可以读取类似于 `isClient` 的 [状态变量](/reference/react/useState),你可以在 [Effect](/reference/react/useEffect) 中将其设置为 `true`: ```html public/index.html

Is Server

``` @@ -314,28 +312,28 @@ export default function App() {
-This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. +这样,初始渲染将呈现与服务器相同的内容,避免不匹配,但是在 hydrate 之后会同步进行额外的渲染。 -This approach makes hydration slower because your components have to render twice. Be mindful of the user experience on slow connections. The JavaScript code may load significantly later than the initial HTML render, so rendering a different UI immediately after hydration may also feel jarring to the user. +这种方法使得 hydrate 变慢,因为你的组件需要渲染两次。要注意在网络连接较慢的情况下用户的体验。JavaScript 代码的加载时间可能会比初始的 HTML 渲染慢很多,因此在 hydrate 之后立即呈现不同的 UI 对用户来说可能也会感到不适。 --- -### Updating a hydrated root component {/*updating-a-hydrated-root-component*/} +### 更新 hydrate 根组件 {/*updating-a-hydrated-root-component*/} -After the root has finished hydrating, you can call [`root.render`](#root-render) to update the root React component. **Unlike with [`createRoot`](/reference/react-dom/client/createRoot), you don't usually need to do this because the initial content was already rendered as HTML.** +在根组件 hydrate 完成之后,你可以调用 [`root.render`](#root-render) 来更新根 React 组件。**与 [`createRoot`](/reference/react-dom/client/createRoot) 不同的是,通常你不需要这样做,因为初始内容已经渲染为 HTML**。 -If you call `root.render` at some point after hydration, and the component tree structure matches up with what was previously rendered, React will [preserve the state.](/learn/preserving-and-resetting-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: +如果在 hydrate 之后某个时刻调用了 `root.render`,并且组件树结构与之前渲染的相匹配,那么 React 将 [保留重置 state](/learn/preserving-and-resetting-state)。请注意,你可以在输入框中输入文字,这意味着在此示例中每秒钟重复调用的 `render` 不会破坏已有的组件状态: ```html public/index.html

Hello, world! 0

``` @@ -370,4 +368,4 @@ export default function App({counter}) {
-It is uncommon to call [`root.render`](#root-render) on a hydrated root. Usually, you'll [update state](/reference/react/useState) inside one of the components instead. +在 hydrate 过的根组件上调用 `root.render` 是不常见的。通常情况下,你可以在组件的内部 [更新 state](/reference/react/useState)。 \ No newline at end of file