react18介绍

改进已有属性,如自动批量处理【setState】、改进Suspense、组件返回undefined不再报错等

支持Concurrent模式,带来新的API,如useTransition、useDeferredValue等

如何升级React 18

npm install react@latest react-dom@latestnpm install @types/react@latest @types/react-dom@latest

react18 使用 ReactDOM.createRoot() 创建一个新的根元素进行渲染,使用该 API,会自动启用并发模式。如果你升级到react18,但没有使用ReactDOM.createRoot()代替ReactDOM.render()时,控制台会打印错误日志要提醒你使用React,该警告也意味此项变更没有造成breaking change,而可以并存,当然尽量是不建议
在这里插入图片描述

import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import App from './app';interface MyModule extends NodeModule {hot: {accept: () => void;};
}
let myM: MyModule = module as MyModule;
if (myM && myM.hot) {myM.hot.accept();
}// ReactDOM.render(<App />, document.querySelector('#root'));
// ReactDOM.createRoot(document.querySelector('#root') as HTMLElement).render(<App />);const container = document.querySelector('#root');// 装载
ReactDOM.createRoot(document.querySelector('#root')).render(<React.StrictMode><App /></React.StrictMode>,
);
// 卸载
ReactDOM.createRoot(document.querySelector('#root')).unmount();

创建根以渲染或卸载的新方法

react18的更新特点

并发模式 Concurrent Mode(并发模式)
  • react18的新特性是使用现代浏览器的特性构建的,彻底放弃对 IE 的支持。
  • 并发模式是实现并发更新的基本前提
  • react18 中,以是否使用并发特性作为是否开启并发更新的依据。
  • 并发特性指开启并发模式后才能使用的特性,比如:useDeferredValue/useTransition

react17 和 react18 的区别就是:从同步不可中断更新变成了异步可中断更新,react17可以通过一些试验性的API开启并发模式,而react18则全面开启并发模式。

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

Automatic Batching自动批量更新state,减少渲染次数

  • react18之前,React Event Handler
  • react18之后,React Event Handler、Promise、setTimeout、native event handler等

如何禁用(不推荐)—— 可以使用ReactDom;提供的flushSync方法

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

react18的新的API

1. Transitions 控制渲染的优先级

新的api是useTransitionstartTransition

渲染分为高优先级和低优先级,高优先级就是正常的state更新,低优先级使用transition Api 包裹

总结:

  • 区别渲染优先级
  • 应对同时大量渲染的情况

比如:当用户在输入框查询数据时,需要实时根据用户输入数据进行搜索提示项的展示。与以往不同的是,提示列表的个数是十分庞大的,每次都在10000条以上。

import {useState} from "react";
import styles from "./index.module.css";
const Home:React.FC = () => {const [val,setVal] = useState('');const [arr,setArr] = useState<number[]>([]);//根据用户输入获取查询列表const getList = (e:any) => {setVal(e.target.value)let arr = Array.from(new Array(10000),item=>Date.now())setArr(arr);}return (<div className={styles.box}><input value={val} onChange={getList}/>{arr.map((item,key)=>(<div key={key}>{item}</div>))}</div>)
}
export default Home;

现象:我们快速在表单输入了abcd,但是很明显出现了卡顿现象,大约2s后表单和列表数据都被渲染。

新的api:在更新大数据更新或者大列表dom时,为了页面性能和渲染优化,我们可以对大数据或列表的更新过程采用startTransition优雅降级处理。

import {useState,startTransition} from "react";
import styles from "./index.module.css";
const Home:React.FC = () => {const [val,setVal] = useState('');const [arr,setArr] = useState<number[]>([]);//根据用户输入获取查询列表const getList = (e:any) => {setVal(e.target.value)let arr = Array.from(new Array(10000),item=>Date.now());startTransition(()=>{setArr(arr);})}return (<div className={styles.box}><input value={val} onChange={getList}/>{arr.map((item,key)=>(<div key={key}>{item}</div>))}</div>)
}
export default Home;

现象:此处的输入框数据优化了许多,并且大数据列表展示卡顿达到了一定程度优化。

注意:useTransition和startTransition的功能一模一样,只是通过hooks的展现方式出现,并且增加了保存列表是否在渲染等待的状态。

第一个变量保存是否渲染中的状态,ture表示渲染等待中

第二个变量和startTransition的使用方式一模一样

import React,{useState,useTransition} from "react";
const Home:React.FC = () => {const [val,setVal] = useState('');const [arr,setArr] = useState<number[]>([]);const [pending,transition] = useTransition()const getList = (e:any) => {setVal(e.target.value)let arr = Array.from(new Array(10000),item=>Date.now())transition(()=>{setArr(arr);})}return (<div className={styles.box}><input value={val} onChange={getList}/>{pending?<h2>loading....</h2>:(arr.map((item,key)=>(<div key={key}>{item}</div>)))}</div>)
}
export default Home;

现象:我们根据useTransition返回的pending状态添加判断,如果列表在渲染中就添加提示加载状态,否则正常显示列表。

2. useDeferredValue——让状态滞后派生

useDeferredValue 的实现效果也类似于 transtion,当迫切的任务执行后,再得到新的状态,而这个新的状态就称之为 DeferredValue。

useDeferredValue 接受一个参数 value ,一般为可变的 state , 返回一个延时状态 deferrredValue。

比如:我们每次的输入或者变化,都会触发一次更新

输入框的值变化的时候,我们使用setTimeout来模拟下向后端请求数据,或者大量计算的耗时操作。这个时候只要输入框的内容发生变化就会触发useEffect,我们用count来进行计数。

import React, {useState, useEffect} from 'react';const List = (props) => {const [list, setList] = useState([]);const [count, setCount] = useState(0);useEffect(() => {setCount(count => count + 1);setTimeout(() => {setList([{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},]);}, 500);}, [props.text]);return [<p>{'我被触发了' + count + '次'}</p>, <ul>{list.map(item => <li>Hello:{item.name} value:{item.value}</li>)}</ul>]
};export default function App() {const [text, setText] = useState("喵爸");const handleChange = (e) => {setText(e.target.value);};return (<div className="App"><input value={text} onChange={handleChange}/><List text={text}/></div>);
};

改造后:

import React, {useState, useEffect,useDeferredValue} from 'react';
import {useDebounce} from 'ahooks';const List = (props) => {const [list, setList] = useState([]);const [count, setCount] = useState(0);useEffect(() => {setCount(count => count + 1);setTimeout(() => {setList([{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},{name: props.text, value: Math.random()},]);}, 500);}, [props.text]);return [<p>{'我被触发了' + count + '次'}</p>, <ul>{list.map(item => <li>Hello:{item.name} value:{item.value}</li>)}</ul>]
};export default function App() {const [text, setText] = useState("喵爸");const deferredText = useDeferredValue(text,{timeoutMs:2000});  const debounceText = useDebounce(text,{wait:2000});useDebounceconst handleChange = (e) => {setText(e.target.value);};return (<div className="App"><input value={text} onChange={handleChange}/><List text={deferredText}/>//比较<List text={debounceText}/></div>);
};

useDeferredValue 和上述 useTransition 本质上有什么异同呢?

相同点:useDeferredValue 本质上和内部实现与 useTransition 一样都是标记成了过渡更新任务。不同点:useTransition 是把 startTransition 内部的更新任务变成了过渡任务transtion,而 useDeferredValue 是把原值通过过渡任务得到新的值,这个值作为延时状态。 一个是处理一段逻辑,另一个是生产一个新的状态。

3.useSyncExternalStore——订阅外部数据源,触发更新

4.useInetionEffect——用于处理css in js缺陷问题

官方对这个函数也不推荐使用,推荐使用useEffect或者useLayoutEffect代替。

5.useId

useId是新增的用于生成唯一ID值的hook钩子,可客户端和服务器端都可以使用,同时避免 dehydrate 过程中数据不匹配的问题。它主要用于与需要唯一 ID 的可访问性 API 集成的组件库。这解决了 React 17 及更低版本中已经存在的问题,但在 React 18 中更为重要,因为新的流式服务器渲染器如何无序交付 HTML。

react18的改进的API

1.setState 都为异步

setState是异步更新的,setState((pre)=>…)此种更新方式将会依赖上一次的状态值,多个state更新会进行批处理更新,减少渲染次数。

import React from 'react';
const Welcome = () => {const [myState, setMyState] = React.useState(1);const [flag, setFlag] = React.useState(true);console.log('render');const handleClick = () => {setMyState((myState) => myState + 6);console.log('myState1', myState);setMyState(myState + 1);setMyState((myState) => myState + 6);console.log('myState2', myState);setFlag((flag) => !flag);setTimeout(() => {setMyState(myState + 1);console.log('myState3', myState);setMyState((myState) => myState + 10);console.log('myState4', myState);}, 1000);};return (<div className="content-box" style={{ height: 'calc(100% - 30px)' }}><h1>Hello world!</h1><p><button onClick={handleClick}>myState:{myState},flag:{flag ? 'true' : 'false'}</button></p></div>);
};
export default Welcome;

2.Suspense——结合异步组件实现条件渲染

import React, { Suspense, useEffect, useState } from 'react'
import User from './pages/User'// 网络请求
// 返回值为  Promise
const fetchUser = async () => {let ret = await (await fetch('/users.json')).json()return ret
}// 创建一个用于解析promise中数据的方法 仿promise的3个状态
const wrapperPromise = promise => {// 定义一个promise的状态let status = 'pending'// 它就是promise解析出来的数据接受的变量let resultconst callbackPromise = promise.then(ret => {// promise执行成功的,返回成功的状态,并把数据赋值给resultstatus = 'success'result = ret},err => {// 把状态修改为失败,并把错误赋值给resultstatus = 'error'result = err})return {// 此方法中,才是把数据获取到read() {if (status === 'pending') {// 抛一个异常,这样它就会再来执行,此时就会有上一次的结果throw callbackPromise} else if (status === 'success') {return result} else if (status === 'error') {return result}}}
}
const User = ({ users }) => {// 通过此方法把promise中的数据读取出来let data = users.read()return (<div><ul>{data.map(item => (<li key={item.id}>{item.name}</li>))}</ul></div>)
}const App = () => {let [data, setData] = useState(wrapperPromise(fetchUser()))return (<div><Suspense fallback={<div>加载中 .......................................</div>}><User users={data} /></Suspense></div>)
}export default App

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/642034.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS2022 在非Qt项目中引用QString、QList等方法

目录 一、新建项目 二、拷贝 三、工程属性设置 四、测试 一、新建项目 在VS中创建了一个c控制台项目&#xff0c;会默认打印“Hello world”&#xff1b; 二、拷贝 需要拷贝的包括QtCore相关的lib, dll, 以及头文件&#xff1b; 1、lib文件 在下述qt安装路径下拷贝Qt5…

[设计模式Java实现附plantuml源码~创建型] 对象的克隆~原型模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

07章【常用类库API】

字符串操作 String类 String可以表示一个字符串。String类实际是使用字符数组存储的。 String类的两种赋值方式&#xff1a; 一种称为直接赋值&#xff1a; String name “小白” 通过关键字new调用String的构造方法赋值 String name new String(“小白”)String类的两…

c++学习理解之路——基类指针指向子类

参考&#xff1a;基类指针指向子类对象_基类指针可以指向子类-CSDN博客 笔记&#xff08;基于自己的理解&#xff0c;欢迎讨论&#xff09; 基类指针对象只存储跟基类中的成员函数、成员对象相关信息&#xff0c;子类指针对象存储了子类和基类中的信息。按道理来说&#xff0c…

【Github】作为程序员不得不知道的几款Github加速神器

背景 众所周知&#xff0c;近几年国内用户在访问Github时&#xff0c;经常间歇性无法访问Github。 接下来推荐几款 作为程序员不得不知道的Github加速神器。 推荐1&#xff1a;FastGithub FastGithub是一款Github加速神器&#xff0c;解决github打不开、用户头像无法加载、r…

【数据结构和算法】--- 二叉树(3)--二叉树链式结构的实现(1)

目录 一、二叉树的创建(伪)二、二叉树的遍历2.1 前序遍历2.2 中序遍历2.3 后序遍历 三、二叉树节点个数及高度3.1 二叉树节点个数3.2 二叉树叶子节点个数3.3二叉树第k层节点个数3.4 二叉树查找值为x的节点 四、二叉树的创建(真) 一、二叉树的创建(伪) 在学习二叉树的基本操作前…

使用Python基于metricbeat和heartbeat采集数据进行告警

一、系统架构 IP主机名角色备注11.0.1.11kafka1kafka和MySQL11.0.1.12kafka2kafka11.0.1.13kafka3kafka11.0.1.14demo1metricbeat和heartbeat 二、部署Kafka 省略 二、部署Metricbeat和Heartbeat metricbeat配置&#xff1a; metricbeat.config.modules:path: ${path.confi…

电商铺货上货接口API实现无货源上货(1688/淘宝/京东/拼多多)

获取商品列表接口 item_search 获取商品详情页数据接口 item_get 1688.item_get 公共参数 获取API测试权限和地址 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包…

Unity Text超框 文字滚动循环显示

Unity Text超框 文字滚动循环显示 //container Text using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.UI;public class AutoScrollText : MonoBehaviour {private Text[] _texts new Text[…

MATLAB字符串编辑常用代码

1.字符串赋值 % 字符串赋值 sabcdefg 2.字符串属性和操作 (1)获取字符串长度 sabcdefg;% 字符串赋值 length(a) % 获取字符串长度 (2)连接字符串 % 连接两个字符串,每个字符串最右边的空格被裁切 s1a s2b s3strcat(s1,s2) 3.字符串比较 % strcmp 比较两个字符串是…

251.【2023年华为OD机试真题(C卷)】5G网络建设(最小生成树算法-JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-5G网络建设二.解题思路三.题解代码Python题解代…

9. UE5 RPG创建UI(下)

在上一篇文章里&#xff0c;制作了显示血量和蓝量的ui&#xff0c;并且还将ui和获取数据使用的控制器层创建出来并初始化成功。现在只有主用户控件上面被添加了控制器层&#xff0c;还未给每个用户控件赋予控制器层。接下来要实现对属性的广播功能&#xff0c;在属性值变化的时…

【Effective C++】4. 设计与声明

Item22 将成员变量声明为private 有以下几个优势&#xff1a; 1. 语法一致性&#xff1a;访问class成员时每一个都是函数&#xff0c;不需要记住是否需要小括号 2. 使成员变量的处理有更精准的控制 class AccessLevels { public:int getReadOnly() const { return readOnly…

【issue-halcon例程学习】fuzzy_measure_pin.hdev

例程功能 检查IC的引线宽度和引线距离。 代码如下 dev_close_window () read_image (Image, board/board-06) get_image_size (Image, Width, Height) dev_open_window (0, 0, Width, Height, black, WindowHandle) * * --- Fuzzy Measure: Row1 : 305.5 Col1 : 375.5 Phi1 …

电商平台接口自动化测试脚本编写规范与实践

随着电商业务的快速发展&#xff0c;电商平台接口的稳定性和可靠性变得越来越重要。为了提高测试效率和保证接口质量&#xff0c;越来越多的企业开始采用自动化测试技术。本文将介绍电商平台接口自动化测试脚本的编写规范与实践&#xff0c;并给出相应的代码示例。 一、编写规…

gitlab.rb主要配置

根据是否docker安装,进入挂载目录或安装目录 修改此文件,我一般是在可视化窗口中修改,有时候也在命令行手敲 将下面的配置复制到该文件中 external_url http://192.168.100.50 # nginx[listen_port] = 8000 (docker安装的这一行不需要,因为端口映射导致此处修改会导致访问…

六使用Maven插件构建Docker镜像

使用Maven插件构建Docker镜像 我们知道&#xff0c;Maven是一个强大的项目管理与构建工具。如果可以使用Maven构建Docker镜像&#xff0c;那么我们的工作就能得到进一步的简化。 经过调研&#xff0c;以下几款Maven的Docker插件进入笔者视野&#xff0c;如表13-1所示。 插件…

C语言学习(3)—— 函数

C语言不支持函数重载 一、函数的使用方法 1. 直接使用 &#xff08;1&#xff09;定义的函数在main函数 之上 #include<stdio.h> int sum(int num1, int num2){int res 0;res num1 num2;return res; }int main(){int res sum(2, 3);printf("%d", res…

大数据学习之Flink、搞懂Flink的恢复策略

第一章、Flink的容错机制 第二章、Flink核心组件和工作原理 第三章、Flink的恢复策略 第四章、Flink容错机制的注意事项 第五章、Flink的容错机制与其他框架的容错机制相比较 目录 第三章、Flink的恢复策略 Ⅰ、恢复策略 1. Checkpoint&#xff1a; 2. Savepoint&#…

Sentinel降级操作

1.通过对feign调用的降级 如果访问失败&#xff0c;则返回另外的信息 正常的feign调用 FeignClient(value "gulimall-seckill",fallback SeckillFeignServiceFallback.class) public interface SeckillFeignService {/*** 写给商品服务的接口&#xff0c;查询秒杀…