React18新特性

简介: React18新特性

React 团队在 2022 年 3 月 29 日正式发布了 React 的第 18 个版本。 我将在这篇文章里简单介绍 React 18

的新特性,React Concurrent Mode(并发模式)的实现,以及简要的升级指南。

New Features

Automatic Batching

早在 React 18 之前,React 就已经可以对 state 更新进行批处理了:

function App() {
  const [count, setCount] = useState(0);
  const [flag, setFlag] = useState(false);
  function handleClick() {
    setCount((c) => c + 1); // Does not re-render yet
    setFlag((f) => !f); // Does not re-render yet
    // React will only re-render once at the end (that's batching!)
  }
  return (
    <div>
      <div>{count}</div>
      <button onClick={handleClick}>Next</button>
    </div>
  );
}

上面这个例子中,用户点击按钮时会产生两次 state 的更新,按理来说每次 state 更新都会导致一次 re-render。但是,这两次更新完全可以合成一次,从而减少无谓的 re-render 带来的性能损失。


这种批处理只限于 React 原生事件内部的更新。


在 React 18 中,批处理支持处理的操作范围扩大了:Promise,setTimeout,native event handlers 等这些非 React 原生的事件内部的更新也会得到合并:

// Before: only React events were batched.
setTimeout(() => {
  setCount((c) => c + 1);
  setFlag((f) => !f);
  // React will render twice, once for each state update (no batching)
}, 1000);
// After: updates inside of timeouts, promises,
// native event handlers or any other event are batched.
setTimeout(() => {
  setCount((c) => c + 1);
  setFlag((f) => !f);
  // React will only re-render once at the end (that's batching!)
}, 1000);

Transitions

Transitions 是 React 中一个用于区分高优更新和非高优更新的新概念

  • 高优的更新/渲染:包括鼠标点击、打字等对实时交互性要求很高的更新场景,卡顿时会影响用户的交互行为,使用户明显感到整个页面卡顿。
  • 非高优的更新/渲染:普通的 UI 更新,不与用户的交互相关,一些对更新实时性要求没那么高的场景。

Suspense

Suspense 是 React 提供的用于声明 UI 加载状态的 API:

<ComponentThatSuspends /> <Sibling /> </Suspense>

上面这串代码里,组件 ComponentThatSuspends 在请求处理数据过程中,React 会在它的位置上展示 Loading 组件。


React 16 和 17 中也已经有 Suspense 了,但是它不是完全体,有许多功能仍未就绪。在 React 团队的计划中,Suspense 的完全体是基于 Concurrent React 的,所以在 React 18,Suspense 相较之前有了一些变化。

Suspense for SSR

React 18 之前的 SSR, 客户端必须一次性的等待 HTML 数据加载到服务器上并且等待所有 JavaScript 加载完毕之后再开始 hydration, 等待所有组件 hydration 后,才能进行交互。即整个过程需要完成从获取数据(服务器)→ 渲染到 HTML(服务器)→ 加载代码(客户端)→ 水合物(客户端)这一套流程。这样的 SSR 并不能使我们的完全可交互变快,只是提高了用户的感知静态页面内容的速度。

React 18 的 Suspense:
服务器不需要等待被 Suspense 包裹组件是否加载到完毕,即可发送 HTML,而代替 Suspense 包裹的组件是 fallback 中的内容,一般是一个占位符(spinner),以最小内联 <script> 标签标记此 HTML 的位置。等待服务器上组件的数据准备好后,React 再将剩余的 HTML 发送到同一个流中。


hydration 的过程是逐步的,不需要等待所有的 js 加载完毕再开始 hydration,避免了页面的卡顿。


React 会提前监听页面上交互事件(如鼠标的点击),对发生交互的区域优先进行 hydration。

Concurrent Rendering

React 18 最重要的更新就是全面启用了 concurrent rendering。它不能算是新功能,实际上是 React 内部工作方式的重大变化。为了最终实现 concurrent rendering,React 布局已久。

问题

在页面元素很多,且需要频繁 re-render 的场景下,React 15 会出现掉帧的现象。其根本原因是大量的同步计算任务阻塞了浏览器的 UI 渲染。JS 运算、页面布局和绘制都是运行在浏览器的主线程当中,他们之间是互斥的。如果 JS 运算持续占用主线程,页面就没法得到及时的更新。当我们更新 state 触发 re-render 时,React 会遍历应用的所有节点,计算出差异,然后再更新 UI。更新一旦开始,中途就无法中断,直到遍历完整棵树,才能释放主线程。如果页面元素很多,整个过程占用的时机就可能超过 16ms,造成浏览器卡顿。


可以看到,React 15 的实现导致浏览器卡顿的关键在于每一次 re-render 开始了就无法停止,所以 React 团队想了一种解决方法:把 re-render 变成 可中断 的。

思路

  • 将 re-render 时的 JS 计算拆分成更小粒度的任务,可以随时暂停、继续和丢弃执行的任务。
  • 当 JS 计算的时间达到 16 毫秒之后使其暂停,把主线程让给 UI 绘制,防止出现渲染掉帧的问题。
  • 在浏览器空闲的时候继续执行之前没执行完的小任务。

升级指南

改变根节点的挂载方式使用新的 API createRoot,使用旧的 API 仍然兼容,只有在使用 createRoot 了之后才会有 React 18 的新特性。


React 18 会启用上面提到的全自动批处理,这算是一个 breaking change,不过 React 也提供了一个 flushSync API 用于退出全自动批处理,用法如下:

import { flushSync } from "react-dom";
function handleClick() {
  flushSync(() => {
    setCounter((c) => c + 1);
  });
  // React has updated the DOM by now
  flushSync(() => {
    setFlag((f) => !f);
  });
  // React has updated the DOM by now
}
  • 如果不用 flushSync 的话两个 setState 只会进行一次 re-render,用了之后会触发两次。
  • TS 类型定义上的较大变化:如果有用到 children,需要在组件 props 的定义中写明它的类型,这在以往是可以忽略不写的。
interface MyButtonProps {
  color: string;
  children?: React.ReactNode;
}
  • React 18 不再支持 IE。
相关文章
|
Cloud Native 安全 中间件
阿里云和中创中间件完成产品集成认证,共同助力基础软件生态建设
近日,山东中创软件商用中间件股份有限公司(以下简称“中创中间件”)产品“中创应用服务器软件V9.1、V10”与阿里云计算有限公司(以下简称阿里云)产品“阿里云PolarDB数据库管理软件V2.0”经过严格测试程序完成产品集成认证测试,此次认证意味着双方在云原生领域正式携手合作。
781 86
阿里云和中创中间件完成产品集成认证,共同助力基础软件生态建设
|
SQL 安全 算法
(*长期更新)软考网络工程师学习笔记——Section 10 网络安全
(*长期更新)软考网络工程师学习笔记——Section 10 网络安全
(*长期更新)软考网络工程师学习笔记——Section 10 网络安全
|
弹性计算 CDN
阿里云服务器香港节点和北京深圳上海杭州地域的区别对比
阿里云中国香港地域服务器和中国大陆地域有什么区别?阿里云百科分别从备案、网络延迟速度及价格三方面来详细对比
1847 0
阿里云服务器香港节点和北京深圳上海杭州地域的区别对比
|
供应链 算法 搜索推荐
商业分析:SheIn是怎样成功的?
SheIn,中文名希音。听名字你可能以为这是一家外国公司,实际上这是一家中国公司,总部在南京,主营业务是跨境女装电商,销售市场都在国外。2021年的销售额超过1000亿人民币,目前估值为500亿美金。
1457 0
商业分析:SheIn是怎样成功的?
|
安全 UED
正版Adobe Photoshop软件0元激活,免费试用
要创造一些真正令人惊叹的作品,您需要使用正版 Adobe 软件!
正版Adobe Photoshop软件0元激活,免费试用
|
SQL JSON 前端开发
一款国产版Postman,好用!
国产版Postman,好用的API管理工具,软件完全免费,堪称国产良心,有兴趣有需求的小伙伴,可以去官网下载。
一款国产版Postman,好用!
|
算法 安全 JavaScript
IOS 某电商App签名算法解析(二) Frida RPC调用
IOS 某电商App签名算法解析(二) Frida RPC调用
IOS 某电商App签名算法解析(二) Frida RPC调用
|
存储 缓存 Java
如何利用 VsCode + evernote + markdown 将自己的博客自动同步成笔记
本文介绍利用 VsCode + evernote + markdown 将自己的博客自动同步成笔记的方法。
如何利用 VsCode + evernote + markdown 将自己的博客自动同步成笔记
|
存储 数据格式 Python
再见 CSV,速度提升 150 倍!
我的原计划是输出100个,目前来看可能最终不一定会到100个,但每个都是超实用且平时经常会遇到的问题。pandas的用法太多了,如果不熟练,平时是需要经常网上查找的,这个系列可以帮助大家快速回忆用法。
再见 CSV,速度提升 150 倍!