createRoot
const root = createRoot(domNode, options?);
options
- 选项参数onRecoverableError
- 在 React 失败时调用;identifierPrefix
- 与useId
搭配使用,通常用于多个根节点场景来避免冲突。
root.render(reactNode)
- 渲染 React 节点- 首次调用会清空根节点下所有 HTML ,然后再渲染 React 组件;
- 可以多次调用,但通常不会这么做。如果组件树结构与之前一致,React 会保存状态。
root.unmount()
- 销毁已渲染的树- 通常不会调用;
- 一旦调用将无法再次调用
render
(否则报错)。
注意点:
- 通常应当只创建一个根节点,且只调用一次
render
; - 只有当 JS 代码加载运行完,用户才会看到渲染的内容。
hydrateRoot
可以将来自服务器的初始 HTML 快照转换为在浏览器中运行的完全可交互应用。
const root = hydrateRoot(domNode, reactNode, options?)
options
- 选项参数(与createRoot
一致)root.render(reactNode)
- 更新渲染 React 节点- 通常不需要调用该方法,因为初始内容已在 HTML 中。
- 如果 hydrate 未完成,调用此方法会清除原 HTML 内容,并切换为客户端渲染。
root.unmount()
- 销毁已渲染的树
注意点:
- 通常应当仅调用一次该方法;
hydrateRoot
期望的渲染内容应当与服务端渲染一致,否则会产生错误:- 原因可能如下:
- 多余的 HTML 空白符;
- 在渲染逻辑中使用了浏览器 API ,或存在针对
window
的判空代码; - 客户端与服务端渲染的数据不一致。
- React 会尝试恢复这种错误,但开发者应当将其视为 bug 去修复;
- 原因可能如下:
对整个文档(从 html
标签开始)进行渲染,可将 document
作为参数:
hydrateRoot(document, <App />);
如果渲染不匹配会不可避免地存在(比如时间戳数据),可以用 suppressHydrationWarning
来消除对元素的 hydrate 处理警告:
<h1 suppressHydrationWarning={true}>
Current Date: {new Date().toLocaleDateString()}
</h1>
这只是一种应急方案,不得滥用。除非是文本内容,React 不会尝试去修补不匹配的内容,直到未来更新的到来。
如果想仅当客户端下渲染内容,可以用诸如下面的代码实现:
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true);
}, []);
return <h1>{isClient ? 'Is Client' : 'Is Server'}</h1>;
从用户体验的角度,应当尽量不使用此类代码,因为组件会被渲染两次。