React 18 新特性

  1. 并发模式(Concurrent Mode):这种新的渲染模式允许在浏览器下一帧空闲时进行更新,允许多个任务同时进行,提高了渲染性能。
    体现在代码上就是 Suspense 组件的应用:
1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { Suspense } from 'react';  

const loadingComponent = () => {
return <div>Loading...</div>;
};

const App = () => {
return (
<Suspense fallback={loadingComponent()}>
<AsyncComponent />
</Suspense>
);
};
  1. 新的更新调度器(Update Scheduler):这个新的更新调度器可以更细粒度地调度更新,以优化更新优先级和时间分片。

React 18引入了一个新的更新调度器,它可以更细粒度地调度更新。这个新的调度器允许React根据任务的优先级和时间分片来安排更新。这意味着React可以根据应用程序的状态和用户交互来优化更新顺序,从而提供更好的用户体验。

以下是一个示例,演示了如何使用新的更新调度器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React, { useState } from 'react';  

const Timer = () => {
const [time, setTime] = useState(Date.now());
const [count, setCount] = useState(0);

useEffect(() => {
const timer = setTimeout(() => {
setTime(Date.now());
setCount(0);
}, 1000);
return () => clearTimeout(timer);
}, []);

return (
<div>
<p>Current time: {time}</p>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};

在这个示例中,我们使用了useState和useEffect来管理状态和执行副作用。在每一秒钟更新时间戳,并在每次点击按钮时增加计数器的值。由于新的更新调度器的引入,React可以根据优先级和时间分片来安排更新,从而提供更好的用户体验。

  1. 新的渲染API:React 18引入了新的渲染API,包括createRoot()函数和Concurrent Mode下的新的渲染函数。
    支持SSR for Suspense:React 18现在支持服务器端渲染(SSR)和Suspense的集成,以改善首屏加载时间和用户体验。

createRoot api 更新前后对比:用 createRoot 替换 render。这样

1
2
3
4
5
6
7
8
9
10
// Before
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);

// After
import { createRoot } from 'react-dom/client';
const container = document.getElementById('app');
const root = createRoot(container); // createRoot(container!) if you use TypeScript
root.render(<App tab="home" />);
  1. 自动批处理(Automatic Batching):在React 18中,当setState被调用后,并不会立即触发重新渲染。React会执行全部事件处理函数,然后触发一个单独的re-render,合并所有的更新。这样可以减少程序数据状态存在中间值导致的不稳定性,也可以提高渲染性能。

代码的体现也同样是 Suspence 组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React, { Suspense } from 'react';  

const loadingComponent = () => {
return <div>Loading...</div>;
};

const App = () => {
return (
<Suspense fallback={loadingComponent()}>
{async () => {
// 在这里执行一些异步操作,例如数据获取等。
const data = await fetchData(); // 假设fetchData是一个异步操作,返回一些数据。
return (
<div>
{data.map((item) => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}}
</Suspense>
);
};