ReactDOM.createRoot
是 React 18 引入的新根 API,与 ReactDOM.render
有何不同?让我们来详细了解一下吧。
👉 ReactDOM.render
每当我们想要显式渲染时,都必须将容器传递给 render 函数。
ini
const container = document.querySelector('#root');
// 初始渲染:容器需要显式访问
ReactDOM.render(<App text="Hello" />, container);
// 后续渲染:容器需要显式访问
ReactDOM.render(<App text="Hello world!" />, container);
👉 ReactDOM.render
接受什么参数?
render 函数接受三个参数:
- 要渲染的 React 元素
- 要在其中进行渲染的 DOM 元素
- 在渲染完成后要执行的函数
并返回相同的容器,但其中包含了已渲染的组件。
php
/**
* @param element - 要渲染的 React 元素
* @param container - 要进行渲染的 DOM 元素
* @param callback - 在渲染完成后要执行的函数
* @return container - 包含已渲染组件的容器
*/
function render(element, container, callback) {
// ...
}
👉 ReactDOM.render
在内部是如何工作的?
ReactDOM.render
执行了一些验证检查:
- 它会验证容器是否是一个合适的节点。
- 它还会验证容器是否之前没有传递给
createRoot
。
然后,它将接收到的所有参数传递给 legacyRenderSubtreeIntoContainer
。
javascript
// 简化的结构
function render(element, container, callback) {
if (isValidContainer(element)) {
throw Error('目标容器不是 DOM 元素');
}
if (isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined) {
// 不会抛出错误,但会将其记录到控制台
error('容器之前已传递给 ReactDOM.createRoot()');
}
return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
}
👉 ReactDOM.createRoot
ReactDOM.createRoot
解决了每次想要显式渲染时都需要传递容器的问题。
ini
// 首先,我们创建一个根
const root = ReactDOM.createRoot(document.querySelector('#root'));
// 初始渲染:容器被隐式访问。
root.render(<App name="Hello" />);
// 后续渲染:容器被隐式访问。
root.render(<App name="Hello world!" />);
👉 ReactDOM.createRoot
接受什么参数?
createRoot
函数仅接受一个必需的参数 ------ 用于渲染的 DOM 元素。 它返回 RootType
,其中包含 render
和 unmount
方法。
注:createRoot
还接受第二个 RootOptions
参数,但我们将在将来进行更详细的讨论。
php
/**
* @param container - 用于渲染的 DOM 元素
* @param options - 相关的选项
* @return RootType - 根实例
*/
function createRoot(container, options) {
// ...
}
👉 ReactDOM.createRoot
在内部是如何工作的?
在 render 函数之上,createRoot
:
- 检查容器是否不是 body 元素。
- 提供了更详细的警告。
然后,createRoot
实例化一个新的 ReactDOMRoot
对象并返回它。完全没有 legacyRenderSubtreeIntoContainer
!
javascript
// 简化的结构
function createRoot(container, options) {
if (isValidContainer(element)) {
throw Error('目标容器不是 DOM 元素');
}
if (container.nodeType === 1 && container.tagName.toUpperCase() === 'BODY') {
console.error('不推荐直接使用 document.body 创建根');
}
if (isContainerMarkedAsRoot(container) {
if (container._reactRootContainer) {
console.error('容器之前已传递给 ReactDOM.render()')
} else {
console.error('容器之前已传递给 createRoot()');
}
}
return new ReactDOMRoot(container, options);
}
翻译自dev.to/fromaline/r... 希望对大家有用