react18介绍

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

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

如何升级React 18

npm install react@latest react-dom@latest

npm 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 now
	flushSync(()=>{
		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});useDebounce



  const 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 result
  const callbackPromise = promise.then(
    ret => {
      // promise执行成功的,返回成功的状态,并把数据赋值给result
      status = 'success'
      result = ret
    },
    err => {
      // 把状态修改为失败,并把错误赋值给result
      status = '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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5分钟做自己的微信红包封面

文章目录 怎么制作自己的红包封面&#xff1f;开通红包封面的要求如下&#xff1a;收费情况制作具体网站&#xff1a;https://chatapi.onechat.fun/register?affYoU6 提交审核logo封面、挂件、气泡证明材料 发放红包封面其他 怎么制作自己的红包封面&#xff1f; 开通红包封面…

OpenCV书签 #结构相似性SSIM算法的原理与图片相似性实验

1. 介绍 结构相似性&#xff08;Structural Similarity&#xff0c;简称SSIM算法&#xff09;&#xff0c;主要用于检测两张相同尺寸的图像的相似度、或者检测图像的失真程度&#xff0c;是一种衡量两幅图像相似度的指标。 定义 给定两个图像 x 和 y&#xff0c;两张图像的结…

第十三讲_ArkUI栅格布局(GridRow/GrowCol)

ArkUI栅格布局&#xff08;GridRow/GrowCol&#xff09; 1. 栅格布局概述2. GridRow的使用2.1 设置栅格布局的总列数2.2 设置栅格布局的排列方向2.3 设置栅格布局中子组件间距 3. GridCol的使用3.1 设置一个GridCol占栅格布局的列数3.2 设置GridCol在栅格布局中偏移列数3.3 设置…

xshell可以远程登录服务器但是vscode一直显示让输入密码的解决方案

vscode报错 但是xshell可以登录 原因&#xff1a;可能因为我上一次没有恰当的退出远程链接导致的&#xff0c;我每次退出远程都是直接强制关闭VScode。 解决方法&#xff1a;打开VScode的 view &#xff08;查看&#xff09; palette&#xff08;命令面板&#xff09;然后输…

读懂比特币—bitcoin代码分析(二)

我们从比特币的客户端启动顺序作为入口来分析代码&#xff0c;先看下面这个函数&#xff1a;AppInitBasicSetup&#xff0c;初始化应用基础设置 bool AppInitBasicSetup(const ArgsManager& args, std::atomic<int>& exit_status) {// ************************…

【Maven】-- 打包添加时间戳的两种方法

一、需求 在执行 mvn clean package -Dmaven.test.skiptrue 后&#xff0c;生成的 jar 包带有自定义系统时间。 二、实现 方法一&#xff1a;使用自带属性&#xff08;不推荐&#xff09; 使用系统时间戳&#xff0c;但有一个问题&#xff0c;就是默认使用 UTC0 的时区。举例…

西瓜书学习笔记——Boosting(公式推导+举例应用)

文章目录 引言AdaBoost算法AdaBoost算法正确性说明AdaBoost算法如何解决权重更新问题&#xff1f;AdaBoost算法如何解决调整下一轮基学习器样本分布问题&#xff1f;AdaBoost算法总结实验分析 引言 Boosting是一种集成学习方法&#xff0c;旨在通过整合多个弱学习器来构建一个…

2024区块链应用趋势,RWA实物资产化

作者 张群&#xff08;赛联区块链教育首席讲师&#xff0c;工信部赛迪特聘资深专家&#xff0c;CSDN认证业界专家&#xff0c;微软认证专家&#xff0c;多家企业区块链产品顾问&#xff09;关注张群&#xff0c;为您提供一站式区块链技术和方案咨询。 实物资产通证化&#xff0…

【开源】基于JAVA语言的智慧社区业务综合平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 业务类型模块2.2 基础业务模块2.3 预约业务模块2.4 反馈管理模块2.5 社区新闻模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 业务类型表3.2.2 基础业务表3.2.3 预约业务表3.2.4 反馈表3.2.5 社区新闻表 四、系统展…

状态空间模型(SSM)是近来一种备受关注的 Transformer 替代技术

状态空间模型&#xff08;SSM&#xff09;是近来一种备受关注的 Transformer 替代技术&#xff0c;其优势是能在长上下文任务上实现线性时间的推理、并行化训练和强大的性能。而基于选择性 SSM 和硬件感知型设计的 Mamba 更是表现出色&#xff0c;成为了基于注意力的 Transform…

VUE+Vis.js鼠标悬浮title提前显示BUG解决方法

在使用VUEVis.js做拓扑图&#xff0c;利用鼠标悬浮放在图标展示设备信息时&#xff0c;发现鼠标一放在图标上面时&#xff0c;标题表会提前在放置的元素下显示&#xff0c;鼠标再放到图标上去元素才会隐藏变成悬浮状态 解决方法&#xff1a; 添加一个div元素&#xff0c;设置v…

C语言入门到精通之练习实例9:输出国际象棋棋盘

题目&#xff1a;要求输出国际象棋棋盘。 程序分析&#xff1a;国际象棋棋盘由64个黑白相间的格子组成&#xff0c;分为8行*8列。用i控制行&#xff0c;j来控制列&#xff0c;根据ij的和的变化来控制输出黑方格&#xff0c;还是白方格。 如果出现乱码情况请参考本博客【C 练习…

前端文件上传(文件上传,分片上传,断点续传)

普通文件上传 思路&#xff1a; 首先获取用户选择的文件对象&#xff0c;并将其添加到一个 FormData 对象中。然后&#xff0c;使用 axios 的 post 方法将 FormData 对象发送到服务器。在 then 和 catch 中&#xff0c;我们分别处理上传成功和失败的情况&#xff0c;并输出相应…

VM虚拟机忘记密码,ISO镜像修改

VM虚拟机忘记密码&#xff0c;ISO镜像修改 制作镜像&#xff1a; 镜像已制作&#xff0c;可在文末链接自行获取从镜像启动系统 1&#xff09;添加IOS镜像文件&#xff1a; 2&#xff09;开机进去固件&#xff1a; 进入后选择对应的驱动器启动 3. 修改密码 点击修改密码软件&a…

苹果、VMware、Apache等科技巨头漏洞被大量应用

Therecord网站披露&#xff0c;黑客因频繁利用多个新发现的漏洞发起攻击吸引了美国网络安全专家们的高度关注&#xff0c;专家们担心这些漏洞可能会被网络犯罪组织和其他各国政府用于不法目的。 过去一周&#xff0c;美国网络安全专家和网络安全与基础设施安全局&#xff08;C…

Dify学习笔记-入门学习(二)

1、官方文档链接 https://docs.dify.ai/v/zh-hans/getting-started/readme 2、 Dify基础介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使开发者可以快速搭建生产级的生成…

鲜花商城,Java项目、前端vue

系统架构 后台&#xff1a; SpringBoot Mybatis-plus Mybatis Hutool工具包 lombok插件 前台&#xff1a;Vue Vue Router ELementUI Axios 系统简介 功能&#xff1a;首页推荐&#xff08;默认根据用户买过的商品进行推荐&#xff0c;如果没买过则根据商品销量推荐&…

8种策略教你有效的ddos攻击防御方法

这篇文章讨论了缓解DDoS&#xff08;分布式拒绝服务&#xff09;攻击的最佳实践。DDoS攻击是一种旨在使目标服务器或网络超载而无法正常工作的恶意行为。文章提出了一系列策略来减轻DDoS攻击的影响&#xff0c;包括流量过滤和封堵、负载均衡和弹性扩展、使用CDN&#xff08;内容…

函数递归和迭代(简单认识)

1.递归思想 把一个大型复杂问题层层转化为一个与原问题相似&#xff0c;但规模较小的子问题来求解&#xff1b;直到子问题不能再被拆分&#xff0c;递归就结束了。所以递归的思考方式就是把大事化小的过程。递归中的递就是递推的意思&#xff0c;归就是回归的意思&#xff0c;…

excel 设置密码保户

目录 前言设置打开密码设置编辑密码 前言 保户自己的数据不被泄漏是时常有必要的&#xff0c;例如财务数据中最典型员工工资表&#xff0c;如果不设置密码后果可想而知&#xff0c;下面我们一起来设置excel查看密码和编辑密码。我用的是wps,其它版本类似&#xff0c;可自行查资…