React 团队最近发布了 React 18 的 alpha 版本。这个版本主要是增强 React 应用程序的 并发渲染 能力,你可以在 React 18 中尝试体验以下几个新特性:

  • 新的 ReactDOM.createRoot() API(替换 ReactDOM.render()

  • 新的 startTransition API(用于非紧急状态更新)

  • 渲染的自动批处理优化(主要解决异步回调中无法批处理的问题)

  • 支持 React.lazy 的 全新 SSR 架构(支持 <Suspense> 组件)

这不,这个版本才刚刚发布社区里已经有很多小伙伴已经跃跃欲试了,我也迫不及待跟着社区的大佬们一起尝试了一下。

感兴趣的小伙伴们可以一起跟着我的记录来试一下:

安装 React 18 Alpha

想要在你的项目里试用 React 18 Alpha,可以尝试执行下面的命令:

npm install react@alpha react-dom@alpha
# or
yarn add react@alpha react-dom@alpha

如果你是使用 Create React App 初始化的项目,你可能会遇到一个由于 react-scripts 引起的 could not resolve dependency 错误:

Could not resolve dependency:
peer react@">= 16" from react-scripts@4.0.3

你可以在安装的时候尝试加上 --force 来解决这个问题:

npm install react@alpha react-dom@alpha --force

ReactDOM.createRoot()

在 React 18 版本中,ReactDOM.createRoot() 替代了通常作为程序入口的  ReactDOM.render() 方法。

这个方法主要是防止  React 18 的不兼容更新导致你的应用程序崩溃。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
const container = document.getElementById('root');
// Create a root.
const root = ReactDOM.createRoot(container);
// Render the top component to the root.
root.render(<App />);

当你更新到 React 18 时,如果你还使用 redner 函数作为程序入口,控制台会打印一个错误日志来提醒你使用 createRoot() ,只有使用了这个方法后才能使用 React 18 新功能。

渲染的自动批处理

React 有一道经典面试题,setState 到底是同步的还是异步的,我面试的时候也会经常问,具体的我在两年前的一篇文章中有介绍过:

由实际问题探究setState的执行机制

class Example extends React.Component {constructor() {super();this.state = {val: 0};}componentDidMount() {this.setState({val: this.state.val + 1});console.log(this.state.val);   this.setState({val: this.state.val + 1});console.log(this.state.val);   setTimeout(() => {this.setState({val: this.state.val + 1});console.log(this.state.val); this.setState({val: this.state.val + 1};console.log(this.state.val);  }, 0);}render() {return null;}
};

比如上面的代码,我们来考虑一下两种情况:

  • 假设 React 完全没有批处理机制,那么执行一个 setState 就会立即触发一次页面渲染,打印顺序应该是 1、2、3、4

  • 假设 React 有一个完美的批处理机制,那么应该等整个函数执行完了之后再统一处理所有渲染,打印顺序应该是 0、0、0、0

实际上,在 React 18 版本之前,上面代码的打印顺序是 0、0、2、3

出现这个问题的主要原因就是在 React 的事件函数和异步回调中的状态批处理机制不一样。在异步回调外面,能够将所有渲染合并成一次,异步回调里面,则不会合并,会渲染多次。

实际上,在大部分的场景下,我们都需要在调用一个接口或者做了一些其他事情之后,再去回调函数里更新状态,上面的批处理机制就会显得非常鸡肋。

现在,React 18 版本解决了这个问题,无论你是在 Promise、setTimeout、或者其他异步回调中更新状态,都会触发批处理,上面的代码真的就会一直打印 0、0、0、0 了!

是不是很棒!React 帮我们消灭的一道面试题 ????。

通常情况下,批处理是没什么问题的,但是有可能在某些特殊的需求(比如某个状态更改后要立刻从 DOM 中获取一些内容)下不太合适,我们可以使用 ReactDOM.flushSync() 退出批处理:

import { flushSync } from 'react-dom'; // Note: react-dom, not reactfunction handleClick() {flushSync(() => {setCounter(c => c + 1);});// React has updated the DOM by nowflushSync(() => {setFlag(f => !f);});// React has updated the DOM by now
}

Ricky 在这篇文章(https://github.com/reactwg/react-18/discussions/21) 详细介绍了 Automatic batching ,感兴趣可以一起到评论区讨论。

SSR 下的懒加载支持

React.lazy 函数能让你像渲染常规组件一样处理动态引入组件。React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 default export 的 React 组件。

const MonacoEditor = React.lazy(() => import('react-monaco-editor'));

React.lazy 必须要配合 <Suspense> 才能更好的使用,在 Suspense 组件中渲染 lazy 组件,可以使用在等待加载 lazy 组件时做优雅降级(比如渲染一些 loading 效果 )。fallback 属性接受任何在组件加载过程中你想展示的 React 元素。

const OtherComponent = React.lazy(() => import('./OtherComponent'));function MyComponent() {return (// Displays <Spinner> until OtherComponent loads<React.Suspense fallback={<Spinner />}><div><OtherComponent /></div></React.Suspense>);
}

React 18 以前, SSR 模式下是不支持使用 Suspense 组件的,而在 React 18 中服务端渲染的组件也支持使用 <Suspense> 了:如果你把组件包裹在了 <Suspense>中,服务端首先会把 fallback 中的组件作为 HTML 流式传输,一旦主组件加载完成,React 会发送新的 HTML 来替换该组件。

<Layout> < Article /> <Suspense fallback={<Spinner />}><Comments /> </Suspense></Layout>

比如上面的代码,<Article> 组件首先会被渲染,<Comments> 组件将被 fallback 替换为 <Spinner> 。一旦 <Comments> 组件加载完成后,React 会才将其发送到浏览器,替换 <Spinner> 组件。

Dan Abramov 在这篇文章(https://github.com/reactwg/react-18/discussions/37) 中详细介绍了这个机制,感兴趣可以到评论区一起讨论。

startTransition API

startTransition 是 React 18 新增加的一个 API,它可以让你区分 非紧急 的状态更新。

比如现在有这样一个场景:我们要去 Input 框输入一个值,然后下面需要同时给出通过我们输入后的值过滤出来的一些数据。

因为你每次需要动态渲染出过滤后的值,所以你可能会将输入的值存储在一个 state 中,你的代码可能是下面这样的:

setInputValue (input) ;
setSearchQuery (input) ;

首先用户输入上去的值肯定是需要立刻渲染出来的,但是过滤出来的联想数据可能不需要那么快的渲染,如果我们不做任何额外的处理,在 React 18 之前,所有更新都会立刻被渲染。

如果你的原始数据非常多,那么每次输入新的值后你需要进行的计算量(根据输入的值过滤出符合条件的数据)就非常大,所以每次用户输入后可能会有卡顿现象。

所以,在以前我们可能会自己去加一些防抖这样的操作去人为的延迟过滤数据的计算和渲染。

新的 startTransition API 可以让我们把数据标记成 transitions 状态。

import { startTransition } from 'react';// Urgent: Show what was typed
setInputValue(input);// Mark any state updates inside as transitions
startTransition(() => {// Transition: Show the resultssetSearchQuery(input);
});

所有在 startTransition 回调中的更新都会被认为是 非紧急处理,如果出现更紧急的更新(比如用户又输入了新的值),则上面的更新都会被中断,直到没有其他紧急操作之后才会去继续执行更新。

怎么样,是不是比我们人工实现一个防抖更优雅 ????

同时,React 还给我们提供了一个带有 isPending 过渡标志的 Hook

import  {  useTransition  }  from  'react' ; const  [ isPending ,  startTransition ]  =  useTransition ( ) ;

你可以使用它和一些 loading 动画结合使用:

{ isPending  &&  < Spinner  / > }

Ricky 在这篇文章(https://github.com/reactwg/react-18/discussions/41) 详细介绍了 startTransition ,感兴趣可以一起到评论区讨论。

React 18 发布计划

React 18 官方介绍(https://github.com/reactwg/react-18/discussions/4)中提到的其他两个 API useDeferredValue<SuspenseList> 还没 released ,我们下次再用,下面是 React 18 的发布时间表:

  • React 18 Alpha 版本:现在就能用

  • 公开的 Beta 版:至少在 Alpha 版本后的几个月

  • RC 版本:至少在 Beta 版发布后的几周

  • 正式版:至少在 RC 版本发布之后的几周

参考

  • https://github.com/reactwg/react-18/discussions/4

  • https://github.com/reactwg/react-18/discussions/41

  • https://github.com/reactwg/react-18/discussions/37

  • https://blog.bitsrc.io/trying-out-react-18-alpha-release-bad9aed12bee

点赞在看 无 bug

【做第一批吃螃蟹的人】试用 React 18 !相关推荐

  1. 快手团购小程序红利来了,想做第一个吃螃蟹的人赶快来

    今天告诉大家可以第一个吃螃蟹的机会.抖音团购相信大家都知道,但是快手也要出团购了,大家知道吗?快手团购将在2022年开始进军到本地生活领域,从开始的美团团购到现在的抖音团购,一直都是近两年比较火爆的项 ...

  2. 鲲鹏迁移第一批吃螃蟹的人,践行技术国际化

    全球化竞争日益激烈的今天,大国都已把科技作为战略博弈的核心.在这样的宏观态势下,核心技术和产品的国产替代迫在眉睫. 以数据中心为例,X86的江湖地位已大不如从前,ARM服务器的崛起正在撬动英特尔一统天 ...

  3. 第一批吃螃蟹的人:浙大全日制英文MBA复试经验分享

          去年浙大全日制MBA项目第一年开始招收全英文,我作为第一批尝试全英文MBA的考生,几经波折总算顺利上岸,听说今年已经没有中文全日制了,把自己去年复试的经验梳理出来,供今年的学弟学妹们参考. ...

  4. 苹果要做第一个吃螃蟹的人!将率先尝试台积电5nm工艺

    [TechWeb]据外媒报道,台积电首席财务官(CFO)何丽梅称,受5G智能手机需求的推动,台积电5纳米制造工艺预计于2020年上半年实现量产,这意味着苹果公司的下一代A系列处理器将率先采用5纳米制造 ...

  5. 苹果14pro Max来了,做第一批吃蟹人

    每年9月,苹果都会发布新款iphone.作为果粉圈老粉丝,已经有12个年头了,从乔布斯发布的iphone4追到现在. 怎么说呢?这个跟自己本身的习惯有很大的关系吧!刚开始用苹果机的时候,吸引自己的一点 ...

  6. 车载VPA形象发展史:谁是第一个吃螃蟹的人?

    今天我们来聊一聊汽车上的虚拟个人助理 它有个洋气的英文名VPA 话说汽车VPA发展到现在 大致可以分为三种类型  嵌入式VPA . 第三方VPA 和  OEM VPA  嵌入式VPA可以直接集成到车辆 ...

  7. 台积电5nm来了!谁会是第一个吃螃蟹的人

    在今年的科技圈新品之中苹果A13芯片无疑是一个焦点,A13相比上一代保持了20%的性能增长,以及40%左右的功耗降低,而此前被寄予厚望的麒麟990虽然使用了最新的7纳米EUV工艺,但是在集成5G的影响 ...

  8. 保险集团CMAF想成为法国量子优势“第一个吃螃蟹的人”

    ​ (图片来源:网络) 11月8日,法国CMAF保险金融集团(Crédit Mutuel Alliance Fédérale)和IBM在巴黎宣布启动转向量子计算的准备工作,包括探索量子计算在银行和保险 ...

  9. 【Swift 适配iOS15】踩坑记录 - 想做次第一个吃螃蟹的人

    昨天iOS15发布了,但是对于开发者来说又多了一些适配问题. 1.UITableView位置下移了? if #available(iOS 15.0, *) {self.mainTableView.se ...

最新文章

  1. 监控Linux服务器网站状态的SHELL脚本
  2. Java Web整合开发(14) -- Struts 1.x 概述
  3. Less和Sass的使用
  4. make mrproper 删除编译产生的相关文件
  5. 参数数组长度_JS数组操作方法总结(二)——pop、shift、push、unshift
  6. python 简单网页_Python爬虫 (一):爬取一个简单的静态网页
  7. Oracle丢失管理员密码的解决方法
  8. 剖析数组名、函数名(不是指针常量,更不是指针)
  9. 每天一个小算法(Shell Sort1)
  10. 输入身份证号,输出出生日期
  11. dayz如何修改服务器指令,【遊戲本體內核心代碼修改】DayZ 有無控制臺刷物品指令、Or設定服務端刷物品MOD...
  12. MySQL 数据库架构
  13. 我的第一个python web开发框架(4)——数据库结构设计与创建
  14. Atitit 机器学习算法分类 目录 1. 传统的机器学习算法 vs 深度学习 1 1.1. 传统的机器学习算法包括决策树、聚类、贝叶斯分类、支持向量机、EM、Adaboost等等。 2 2. 监
  15. 英特尔第十代处理器为什么不支持win7_为什么7代CPU不支持WIN7,原因是什么
  16. 中南大学19软工上岸青年的一点考研经验
  17. 全国各省市区域mysql_中国省市区数据表(MySQL版)
  18. 《15款最好用的新浪短链接(t.cn接口)在线生成工具》
  19. c语言生成exe文件,打开exe文件闪退怎么办
  20. 群辉nas虚拟linux,UNRAID教程:3分钟 用unraid自带的虚拟机 安装 黑群晖NAS DSM系统 很强大!...

热门文章

  1. java 死锁bdm
  2. 北大本科计算机教材,北大失去自考计算机专业教材编印权和命题权之后(上)...
  3. 《Python Web开发实战》踩地雷记17/3/24
  4. 基于51单片机的水位水质检测系统方案原理PCB设计
  5. EM算法:从极大似然估计导出EM算法(还算通俗易懂)
  6. 基于java的推箱子游戏系统设计与实现(项目报告+答辩PPT+源代码+部署视频)
  7. 划片机在测高过程中发生异常如何自查
  8. m5C-RNA—掀起表观转录组学研究新浪潮
  9. 苹果你永远不会懂!华硕T300多形态本首测
  10. Sony Ericsson SDK 2.5.0.1 的正确下载地址