跳到主要内容

渲染入口

回想一下我们在使用React的时候,它的入口文件通常是这样的:

import React from "react";
import ReactDOM from "react-dom/clent";

const element = <h1>Hello, world!</h1>;
ReactDOM.render(element, document.getElementById("root"));

在每个React项目中,都会有一个入口文件,这个入口文件就是我们的渲染入口,它会将我们的React组件渲染到页面中。

而这个渲染入口,就是ReactDOM.render

ReactDOM.render

在这里,我们先来看一下ReactDOM.render的源码,它的源码在ReactDOM.render

这里需要值得说一下的是,在React 18之前,ReactDOM.render是从react-dom中导出的。

但是在React 18中,ReactDOM.render是从react-dom/client中导出的,这是因为在React 18中,React为了更好的支持服务端渲染,它将ReactDOM.render进行了拆分,拆分成了ReactDOM.hydrateReactDOM.createRoot,而ReactDOM.render就是这两个方法的一个封装,具体可以看一下React 18 Upgrade Guide

由于本文中只是探讨React的客户端渲染,所以我们就不去深究React 18中的服务端渲染了,至于服务端渲染,那又是一个很大的话题,我会在后面的文章中进行总结。

createRoot

通过render的源码一层层的追踪,我们最终会发现,ReactDOM.render的实现是通过调用ReactDOM.createRoot来实现的。

ReactDOM.createRoot的源码在ReactDOM.createRoot

Fiber

在React 16之前,React的渲染过程是通过递归的方式来实现的,但是递归的方式有一个很大的问题,就是递归过程中无法中断,所以当组件树很深的时候,递归的过程就会很长,这就会导致页面卡顿,而且在递归过程中,无法中断,所以当我们在递归过程中,修改了组件树,那么这个时候就会出现问题。

为了解决这个问题,React在16版本中,引入了Fiber架构,Fiber架构的核心思想就是将递归的渲染过程改成循环的渲染过程,这样就可以实现中断,而且在循环过程中,也可以中断,这样就可以实现异步渲染。

在React 16中,Fiber架构是一个实验性的功能,所以默认是不开启的,如果想要使用Fiber架构,那么需要在ReactDOM.render中传入{ unstable_isConcurrent: true },这样才能开启Fiber架构。

而在React 17中,Fiber架构已经成为了默认的渲染方式,所以我们不需要再传入{ unstable_isConcurrent: true },React会自动开启Fiber架构。

Concurrent Mode

在React 18中,React将Fiber架构进行了升级,它将Fiber架构进行了拆分,拆分成了两个部分,分别是Concurrent Mode和Sync Mode。

Concurrent Mode是并发模式,它是React的默认模式,它会将渲染过程拆分成多个任务,然后将这些任务分配到不同的帧中,这样就可以实现异步渲染,而且在渲染过程中,也可以中断。

Sync Mode是同步模式,它会将渲染过程拆分成多个任务,但是这些任务会在同一帧中执行,所以它是同步渲染,而且在渲染过程中,也无法中断。

在React 18中,默认是开启Concurrent Mode的,如果想要使用Sync Mode,那么需要在ReactDOM.render中传入{ unstable_isConcurrent: false }

那么这两个模式有什么区别呢?

我们可以通过下面这个例子来看一下:

import React from "react";

function App() {
const [count, setCount] = React.useState(0);

return (
<div>
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}

ReactDOM.render(<App />, document.getElementById("root"));

在这个例子中,我们有一个按钮,当我们点击这个按钮的时候,会修改count的值,然后将count的值显示在页面中。

在这个例子中,我们使用的是Concurrent Mode,所以当我们点击按钮的时候,页面不会卡顿,而是会立即更新。

如果我们将Concurrent Mode改成Sync Mode,那么当我们点击按钮的时候,页面就会卡顿,因为在Sync Mode中,渲染过程是同步的,所以当我们点击按钮的时候,渲染过程就会一直执行,直到渲染完成,这个过程中,页面就会卡顿。