概述
React 18
React 18
提供了全新的根节点创建方式:ReactDOM.createRoot()
以此来开启React 18
的全部新特性
React
历代版本迭代想要解决的事两类导致网页卡顿的问题:cpu密集型任务
和io密集型任务
,React18
提出的并发特性(Concurrent Rendering
)就是为了解决上述问题。
Concurrent Rendering
React 18
引入了并发渲染的特性,可以概括为以下两点:
- 时间分片:在
Concurrent Rendering
模式下当更新任务的render
过程无法在浏览器的一帧内完成时,会被分为多个任务进行可中断的更新,以此来保证浏览器的每一帧都有空余时间进行绘制,时间分片是Concurrent
实现的基础 - 更新优先级:在
Concurrent Rendering
模式下更新任务会带有优先级,低优先级任务的执行将让位于高优先级任务。同一上下文中的高优先级任务先执行,不同上下文中的高优先级任务将打断正在执行的低优先级任务
Concurrent Rendering与React 18之前的渲染模式进行对比
React 18
之前的渲染模式是legacy
模式,使用reactDOM.render
创建的react
应用都是使用这种模式
为了进行对比,我写了一个demo
,在demo
中用一个定时器延迟1000ms
模拟接口请求渲染一个列表,另一个定时器延迟1040ms
模拟触发一次点击事件,然后我打开F12
,使用Performance
录制一段脚本,然后移动到1000ms
左右的位置,可以看到列表请求触发的更新和点击事件触发的更新先后进行render
,而列表更新的整个过程处于一个宏任务中且耗时200多ms
,浏览器每16.67ms
刷新一次,这导致render
的过程中浏览器的每一帧都没时间绘制,反应到真实的场景中就是用户感到点击操作卡顿
通过这个demo
可以看出legacy
模式下所有的更新都是同步调度的,没有优先级之分
而使用Concurrent Rendering
观察到点击事件的出发的更新打断了正在进行的render
优先执行,提交到视图后继续进行列表渲染的render
通过这个demo
实验我也是得出了以下几个结论:
- 使用
Concurrent Rendering
会给任务分优先级 - 当更新的
render
流程过于耗时而超过浏览器一帧的时间时,更新任务将被分割为多个任务进行可中断的更新,每个任务的执行时间不超过16ms
。这使得浏览器的每一帧中有空余时间进行绘制,点击事件的更新可以优先呈现到视图中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BBv1q2ls-1663847326775)(https://secure2.wostatic.cn/static/uNVouaRder2x9BDLUxdY3h/image.png)]
startTransition
startTransition
主要为了能大量的任务下也能保持UI
响应,可以将特定更新表记为“非紧急”来改善用户交互。
import { startTransition } from 'react';
// 紧急:显示输入的内容
setInputValue(input);
// 标记回调函数内的更新为非紧急更新
startTransition(() => {
setSearchQuery(input);
});
被startTransition
包裹的setState
触发的渲染被标记为不紧急渲染,这些渲染会被其它紧急渲染所抢占。
在React 18
之前没有更新优先级的概念,所有更新都要排队,不管优先级高不高,都要等带上一个更新结果才能执行。而用户对于不同交互的执行速度与其是不同的,我们可以使用startTransition
赋予不同的任务不同的优先级来满足用户的预期。比如:
- 高优先级任务:用户输入、窗口缩放、窗口拖拽
- 低优先级任务:数据请求和文件下载
setState合并更新
在React 18
之前,setState
在React
的合成事件中是合并更新的,在setTimeout
的原生事件中是同步按序更新的。例如:
handleClick = () => {
this.setState({ age: this.state.age + 1 });
console.log(this.state.age); // 0
this.setState({ age: this.state.age + 1 });
console.log(this.state.age); // 0
this.setState({ age: this.state.age + 1 });
console.log(this.state.age); // 0
setTimeout(() => {
this.setState({ age: this.state.age + 1 });
console.log(this.state.age); // 2
this.setState({ age: this.state.age + 1 });
console.log(this.state.age); // 3
});
};
而在React 18
中,不论是在合成事件中,还是在宏任务中,都是会合并更新
function handleClick() {
setState({ age: state.age + 1 }, onePriority);
console.log(state.age);// 0
setState({ age: state.age + 1 }, onePriority);
console.log(state.age); // 0
setTimeout(() => {
setState({ age: state.age + 1 }, towPriority);
console.log(state.age); // 1
setState({ age: state.age + 1 }, towPriority);
console.log(state.age); // 1
});
}
Suspense
Suspense
用于组件在渲染完成之前的等待期间显示Suspense
的callback
中的内容,Suspense
内的组件子树比其它组件数优先级更低。
最后
以上就是糊涂热狗为你收集整理的React 18新特性的全部内容,希望文章能够帮你解决React 18新特性所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复