React 18 新特性
- 并发模式(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> ); };
|
- 新的更新调度器(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可以根据优先级和时间分片来安排更新,从而提供更好的用户体验。
- 新的渲染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
| import { render } from 'react-dom'; const container = document.getElementById('app'); render(<App tab="home" />, container);
import { createRoot } from 'react-dom/client'; const container = document.getElementById('app'); const root = createRoot(container); root.render(<App tab="home" />);
|
- 自动批处理(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(); return ( <div> {data.map((item) => ( <div key={item.id}>{item.name}</div> ))} </div> ); }} </Suspense> ); };
|