我是靠谱客的博主 糊涂热狗,最近开发中收集的这篇文章主要介绍React 18新特性,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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之前,setStateReact的合成事件中是合并更新的,在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用于组件在渲染完成之前的等待期间显示Suspensecallback中的内容,Suspense内的组件子树比其它组件数优先级更低。

最后

以上就是糊涂热狗为你收集整理的React 18新特性的全部内容,希望文章能够帮你解决React 18新特性所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部