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.rhkb.cn/news/244495.html

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

相关文章

python pip安装包时,出现 WARNING: Ignoring invalid distributio xxxx,解决办法

pip安装包时&#xff0c;出现 WARNING: Ignoring invalid distributio xxxx&#xff0c;解决办法 遇到的问题&#xff0c;如图 这个问题其实就是python环境下的包无效了&#xff0c;找到WARNING: Ignoring invalid distributio xxxx后面对应的路径&#xff0c;删除对应的~XXXX…

Android开发--状态栏布局隐藏的方法

1.问题如下&#xff0c;安卓布局很不协调 2.先将ActionBar设置为NoActionBar 先打开styles.xml 3.使用工具类 package com.afison.newfault.utils;import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.graph…

TortoiseSVN源码安装与迁移全攻略

一、前言 随着版本控制系统的普及&#xff0c;越来越多的开发者和团队开始使用SVN&#xff08;Subversion&#xff09;来管理代码。本文将详细介绍TortoiseSVN的源码安装及迁移过程&#xff0c;帮助您轻松掌握这一版本控制工具。 二、TortoiseSVN源码安装 依赖环境安装&…

Window安装Python和开发Pycharm

准备&#xff1a; 1&#xff1a;安装Python环境 https://www.python.org/downloads/windows/ 2: 下载Pycharm https://www.jetbrains.com/pycharm/download/other.html

快速排序

快速排序 概况步骤代码示例输出结果 要想学习快速排序&#xff0c;前提必须了解 递归算法 概况 快速排序是一种高效的排序算法&#xff0c;它采用了分治的策略。 基本思想是选择一个基准数&#xff0c;通过一趟排序将待排序序列划分成两个子序列&#xff0c;其中一个子序列的…

乔迁新居发言

亲爱的家人们&#xff0c;大家好&#xff01; 非常感谢大家在百忙之中抽出宝贵的时间来到这里为我们的新居增添福气。我代表我和田小帆对大家的到来表示热烈的欢迎和衷心的感谢。 在这个特殊的时刻&#xff0c;我对我们小家庭建设过程中帮助我们的所有亲人、朋友和同学们表示由…

大模型实战营Day6 笔记

本期主题为&#xff1a; 为何测评&#xff0c;因场景众多&#xff0c;需要统一的标准&#xff1a; 评测的意义&#xff1a; 传统NLP的一些评测需要&#xff1a; 到了大模型时代&#xff0c;需要评测的就更多了&#xff1a; 客观评测&#xff1a; 有些主观题可以用模型评价…

Shell脚本的条件语句-------if语句与case语句

目录 一、if语句 1、bash的配置文件 2、单分支结构 3、双分支结构 4、多分支结构 ①单分支应用举例&#xff1a;写一个脚本检查80端口是否开启&#xff0c;如果开启则反馈http正在运行&#xff0c;否则启动httpd服务 ②多分支应用例子&#xff1a;90-100 是优秀 70-89…

FlinkAPI开发之状态管理

案例用到的测试数据请参考文章&#xff1a; Flink自定义Source模拟数据流 原文链接&#xff1a;https://blog.csdn.net/m0_52606060/article/details/135436048 Flink中的状态 概述 有状态的算子 状态的分类 托管状态&#xff08;Managed State&#xff09;和原始状态&…

springboot123基于springboot框架的网上商城系统的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的基于springboot框架的网上商城系统的设计与实现 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看…

centos7.9安装redmine5.1.1

前提&#xff1a; 安装mysql并新建数据库--教程太多了此步骤省略&#xff1b; 用sqlyog连上mysql创建数据库redmine&#xff1b; 1.下载redmine-5.1.1.tar.gz&#xff0c;上传到/usr/local/software目录下&#xff1b; 2.解压 cd /usr/local/software tar -zxvf redmine-5.…

架构师的36项修炼-06高性能系统架构设计

本课时讲解大家常听到的高性能系统架构。 高性能系统架构&#xff0c;主要包括两部分内容&#xff0c;性能测试与性能优化。性能优化又可以细分为硬件优化、中间件优化、架构优化及代码优化&#xff0c;知识架构图如下。 性能测试 先看系统的性能测试。性能测试是性能优化的…

Mybatis 动态SQL条件查询(注释和XML方式都有)

需求 : 根据用户的输入情况进行条件查询 新建了一个 userInfo2Mapper 接口,然后写下如下代码,声明 selectByCondition 这个方法 package com.example.mybatisdemo.mapper; import com.example.mybatisdemo.model.UserInfo; import org.apache.ibatis.annotations.*; import j…

GetShell的姿势

0x00 什么是WebShell 渗透测试工作的一个阶段性目标就是获取目标服务器的操作控制权限&#xff0c;于是WebShell便应运而生。Webshell中的WEB就是web服务&#xff0c;shell就是管理攻击者与操作系统之间的交互。Webshell被称为攻击者通过Web服务器端口对Web服务器有一定的操作权…

AnimatedDrawings:让绘图动起来

老样子&#xff0c;先上图片和官网。这个项目是让绘制的动画图片动起来&#xff0c;还能绑定人体的运动进行行为定制。 快速开始 1. 下载代码并进入文件夹&#xff0c;启动一键安装 git clone https://github.com/facebookresearch/AnimatedDrawings.gitcd AnimatedDrawingspip…

python批量处理修改pdf内容

将PDF转换为Word&#xff1a; 使用pdf2docx库中的Converter类来进行PDF转换。convert_pdf_to_docx函数接受PDF文件路径和输出的Word文档路径作为参数。通过调用Converter对象的convert方法将PDF转换为Docx格式。最后调用close方法关闭Converter对象并保存转换后的文档。 将Word…

一文读懂RabbitMQ核心概念及架构

1. RabbitMQ简介 RabbitMQ是一个开源的消息代理软件&#xff0c;实现了高级消息队列协议&#xff08;AMQP&#xff09;。它是一个应用程序对应用程序的通信方法&#xff0c;基于消费-生产者模型。在RabbitMQ中&#xff0c;消息的生产者将消息发布到队列中&#xff0c;而消息的…

【zlm】针对单个设备的码率的设置

目录 代码修改 实验数据一 实验数据二 同时拉一路视频后 修改记录 使用方法 各库实操 代码修改 要被子类引用 &#xff0c;所以放在protected 不能放private 下面的结论&#xff0c;可以在下面的实验数据里引用。“同时拉一路视频后” 实验数据一 https://10.60.3.45:1…

共话 AI for Science | 北京大学王超名:BrainPy,迈向数字化大脑的计算基础设施

导读&#xff1a; 2023 和鲸社区年度科研闭门会以“对话 AI for Science 先行者&#xff0c;如何抓住科研范式新机遇”为主题&#xff0c;邀请了多个领域的专家学者共同探讨人工智能在各自领域的发展现状与未来趋势。 在脑科学领域&#xff0c;数字化大脑通过数学模型和计算机…

Matplotlib Mastery: 从基础到高级的数据可视化指南【第30篇—python:数据可视化】

文章目录 Matplotlib: 强大的数据可视化工具1. 基础1.1 安装Matplotlib1.2 创建第一个简单的图表1.3 图表的基本组件&#xff1a;标题、轴标签、图例 2. 常见图表类型2.1 折线图2.2 散点图2.3 条形图2.4 直方图 3. 图表样式与定制3.1 颜色、线型、标记的定制3.2 背景样式与颜色…