首页IT科技react 新版本(React18升级和React18新特性)

react 新版本(React18升级和React18新特性)

时间2025-05-04 22:30:51分类IT科技浏览4515
导读:背景: React官方在2022年3月29日React18版本正式发布了。...

背景:

React官方在2022年3月29日React18版本正式发布了            。

可以在官网看到            ,react 17 的发布时间是 2020 年 10 月 20 号                 ,距离 React 18 发布足足间隔一年半      ,并且v17中只有三个小版本         ,分别是17.0.0            、17.0.1                  、17.0.2

并且一直到React18发布                 ,React17都没有任何更新         ,可以说React17只是作为React18的垫脚石                  。

升级原因:

React18的并发更新和自动批处理可以提升项目性能     。

2. 提高项目的兼容性

在项目使用React17的时候      ,如果依赖的组件使用的React18版本可能导致项目因为版本不匹配而发生错误甚至奔溃(亲测有效)         。而项目如果使用了React18                 ,依赖的其他组件使用React18或者React17都可以很好的兼容                  。

升级:

新项目: 直接使用npm 或这 yarn安装即可        。 npm install react react-dom --save yarn install react react-dom --save 老项目: 将package.json中的react版本改为18            ,删除node_modules文件

再执行npm install即可      。

项目中的需要修改的地方:

1. 挂在组件时:ReactDOM.render

// React 17 import React from react; import ReactDOM from react-dom; import App from ./App; const root = document.getElementById(root)!; //React 18 // React 18 import React from react; import ReactDOM from react-dom/client; import App from ./App; const root = document.getElementById(root)!; ReactDOM.createRoot(root).render(<App />);

2. 卸载组件时: unMountComponentAtNode升级为root.unmount

// React 17 ReactDOM.unmountComponentAtNode(root); // React 18 root.unmount();

3. 删除了render中的回调函数                  。

如果项目中有在render中用到了回调函数   ,迁移到对应组件的useEffect中即可           。

// React 17 const root = document.getElementById(root)!; ReactDOM.render(<App />, root, () => { console.log(渲染完成); }); // React 18 const AppWithCallback: React.FC = () => { useEffect(() => { console.log(渲染完成); }, []); return <App />; }; const root = document.getElementById(root)!; ReactDOM.createRoot(root).render(<AppWithCallback />);

4. typeScript中需要手动定义children

在项目中定义props类型的时候                 ,如果需要获取字组件children需要显示的定义它   。

5. setState自动批处理

什么是批处理?

批处理就是多个状态更新合并成一个次更新                  。(视图层将多次渲染合并成一次渲染)

在React18以前

我们只在React18中进行批处理              。默认情况下               ,在promise     、setTimeout         、原生事件处理函数中                  、或任何其它事件内的更新都不会进行批处理。

在React18以后

所有更新都会自动进行批处理               。多次更新将会合并成一次更新,从而降低渲染次数提高性能                 。

改动点:

如果项目中有通过promise        、setTimeout      、原生事件处理函数去解决批处理的问题在React18中将不会生效了  。

如果再想退出批处理              ,需要使用flushSync

import React, { useState } from react; import { flushSync } from react-dom; const App: React.FC = () => { const [count1, setCount1] = useState(0); const [count2, setCount2] = useState(0); return ( <div onClick={() => { flushSync(() => { setCount1(count => count + 1); }); // 第一次更新 flushSync(() => { setCount2(count => count + 1); }); // 第二次更新 }} > <div>count1: {count1}</div> <div>count2: {count2}</div> </div> ); }; export default App;

6. react组件返回空值

在react17中                 ,如果你需要返回一个空组件   ,ract只允许你返回null            。如果你显示的返回了undifined控制台则会在运行时抛出一个错误                  。

在react18中            ,不在见出啊因返回undifined而导致奔溃     。即能返回null                 ,也能返回undifned         。

Concurrent Mode(并发模式)

并发模式可帮助应用保持响应      ,并根据用户的设备性能和网速进行适当的调整         ,该模式通过使渲染可中断来修复阻塞渲染限制                  。在 Concurrent 模式中                 ,React 可以同时更新多个状态        。

react17 和 react18的区别就是:从同步不可中断更新变成了异步可中断更新      。

开启并发模式:

在React18中提供了新的root Api         ,我们只需要把render改成ReactDOM.createRoot(root).render(<App />) 就可以开启并发模式                  。

开启并发模式就一定开启并发更新吗?

No!在React18中开启并发模式不一定开启并发更新      ,而是否开启并发更新的依据是是否使用并发特性           。

并发特性指的是开启并发模式才能使用的特性                 ,比如下面介绍的:

startTranstion useTranstion useDeferredValue

结论:

并发更新的意义就是交替执行不同的任务            ,当预留的时间不够用时   ,React将线程控制交给浏览器                 ,等待下一帧时间的到来               ,然后继续被中断的工作   。

并发模式是实现并发更新的基本前提                  。 时间切片是实现并发更新的基本手段              。

Transition:

在大屏幕视图更新的时,startTransition 能够保持页面有响应              ,这个 api 能够把 React 更新标记成一个特殊的更新类型 transitions                  ,在这种特殊的更新下   ,React 能够保持视觉反馈和浏览器的正常响应。

1. startTransition:

startTransition(scope)

scope 是一个回调函数            ,里面的更新任务都会被标记成过渡更新任务                 ,过渡更新任务在渲染并发场景下      ,会被降级更新优先级         ,中断更新               。

使用:

startTransition(()=>{ /* 更新任务 */ func() })

startTranstion的回调包裹的setState触发的渲染标记为不紧急渲染                 。这些渲染可能被其他紧急渲染所抢占  。

2. useTranstion

在低优先级还没执行的时候                 ,怎么知道过渡任务处于什么状态         ,这时候就可以使用useTranstion这个Hooks            。useTranstion执行返回一个数组      ,数组有两个状态值                  。

第一个状态值: 当处于过渡状态的标记     。

第二个状态值: 可以理解为startTranstion                 ,将任务标记为过渡任务         。

import { useTranstion } from react; const [isPending, startTrastion] = useTranstion();

3. useDeferredValue

返回一个延时响应的值可以让一个state延时生效            ,只有当前没有紧急更新的任务时   ,该值才会变为最新的值                  。和startttanstion一样都是标记为非紧急更新        。

useTranstion和useDeferredValue异同:

相同点: useDeferredValue本质上和内部实现与useTranstion一样都是标记成了过度更新任务      。

不同点:useTranstion是把startTranstion内部的更新任务变成了过度任务transtion                 ,而useDeferredValue是把原值通过过度任务得到新的值               ,这个值作为延时状态,一个是处理逻辑              ,一个是生产一个新的状态                  。

例子

输入框输入一个内容                 ,更新10000条列表内容           。在chrome仓库看执行栈   。

使用并发特性:

我们可以看到使用并发特性

此时我们的任务被拆分到每一帧不同的task中   ,JS脚本执行的时间大体在5ms左右            ,这样浏览器就有剩余的时间执行页面的样式布局和页面重绘                  。

使用普通更新:

我们可以看到只有一次页面的重绘                 ,其他几次输入都因为输入触发js的执行而阻塞了更新              。

新的api

一, useId

const id = useId();

支持同一个组件在客户端和服务端生成相同的唯一的 ID      ,避免 hydration 的不兼容         ,这解决了在 React 17 及 17 以下版本中已经存在的问题。因为我们的服务器渲染时提供的 HTML 是无序的                 ,useId 的原理就是每个 id 代表该组件在组件树中的层级结构               。

二         , useSyncExternalStore

useSyncExternalStore是一个新的api      ,经历了一次修改                 ,由useMutableSource改变而来            ,主要用来解决外部数据撕裂的问题                 。

三   , useInsertionEffect

在dom生成之后                 ,useLayoutEffect之前               ,它的工作原理大致合useLayoutEffect相同,只是此时无法访问DOM节点的引用              ,一般用于提前注入<style>脚本  。

react17-react18

参考地址: react/CHANGELOG.md at main · facebook/react · GitHub

声明:本站所有文章                 ,如无特殊说明或标注   ,均为本站原创发布            。任何个人或组织            ,在未征得本站同意时                 ,禁止复制                  、盗用           、采集   、发布本站内容到任何网站                  、书籍等各类媒体平台                  。如若本站内容侵犯了原著者的合法权益      ,可联系我们进行处理     。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
排名大幅提升(排名有所提升) 可以挂机赚钱的小游戏(有什么挂机赚钱游戏-可玩的游戏太少,挂机手游却能大行其道,肝帝爱用时间换取成就感)