react18介绍

这篇具有很好参考价值的文章主要介绍了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,而可以并存,当然尽量是不建议
react18介绍,前端,react18

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更新会进行批处理更新,减少渲染次数。文章来源地址https://www.toymoban.com/news/detail-821235.html

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

到了这里,关于react18介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React18新特性?

    hello world欢迎来到前端的新世界 😜当前文章系列专栏:react.js 🐱‍👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误,感谢大家指出)🌹 💖感谢大家支持!您的观看就是作者创作的动力 早在 React 18 之前,React 就已经可以对 stat

    2024年02月06日
    浏览(28)
  • react18虚拟滚动列表

    不依赖第三方,借用react18api和原生JS实现一个虚拟滚动列表,如果你的项目比较小,又不想引入第三方的框架,可以拿去用; style样式 核心HTML 逻辑代码

    2024年02月19日
    浏览(34)
  • React18-树形菜单-递归

    https://github.com/dL-hx/manager-fe/commit/85faf3b1ae9a925513583feb02b9a1c87fb462f7 从接口获取城市数据,渲染出一个树形菜单 要求: 可以展开和收起 学会递归渲染出一个树形菜单, 并点击后可以展开和收起 通过对数据上添加控制字段(show)避免在子组件添加各种同步的useState,等字段.保证单向数据

    2024年01月22日
    浏览(72)
  • React18 之 Suspense

    我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。 本文作者:佳岚 Suspense 组件我们并不陌生,中文名可以理解为 暂停or悬停  , 在 React16 中我们通常在路由懒加载中配合 Lazy 组件一起使

    2024年03月09日
    浏览(38)
  • React 18 渲染和提交

    参考文章 组件显示到屏幕之前,其必须被 React 渲染。理解这些处理步骤将有助于思考代码的执行过程并能解释其行为。 React 请求和提供 UI 的过程总共包括三个步骤: 触发 一次渲染 渲染 组件 提交 到 DOM 触发 —— 渲染 —— 提交 有两种原因会导致组件的渲染: 组件的 初次

    2024年02月13日
    浏览(55)
  • React源码解析18(1)------ React.createElement 和 jsx

    我们知道在React17版本之前,我们在项目中是一定需要引入react的。 import React from “react” 即便我们有时候没有使用到React,也需要引入。原因是什么呢? 在React项目中,如果我们使用了模板语法JSX,我们知道它要先经过babel的转译。那babel会将JSX转换成什么样子的格式呢? 可

    2024年02月13日
    浏览(37)
  • React 18 选择 State 结构

    参考文章 构建良好的 state 可以让组件变得易于修改和调试,而不会经常出错。以下是在构建 state 时应该考虑的一些建议。 当编写一个存有 state 的组件时,需要选择使用多少个 state 变量以及它们都是怎样的数据格式。尽管选择次优的 state 结构下也可以编写正确的程序,但有

    2024年02月10日
    浏览(55)
  • React18从入门到实战

    创建react项目的更多方式 使用 npx react-create-app react-basic项目名称 创建 启动项目 打包项目 启动测试运行项目 将项目中隐藏的webpack配置释放出 以上就是package文件中存放项目核心包的地方 这个地方是项目中可执行的一些命令 将其中除去index.js和app.js的文件全部删掉并分别进入

    2024年04月11日
    浏览(30)
  • React18 hook学习笔记

    useState useState用于在函数组件中声明和管理状态 它接受初始状态,并返回一个状态变量和一个更新状态的函数 通过调用更新状态的函数,可以改变状态的值并触发组件的重新渲染 useEffect React的useEffect钩子可以让开发者在函数组件中管理副作用。 副作用操作是指那些与组件渲

    2024年02月14日
    浏览(40)
  • 【react】react18的学习(十一)– 底层原理(一)之 diff 算法

    diff算法、fiber链表 步骤:(追求多复用,快渲染) 首次渲染,缓存虚拟dom或fiber链表(17及以后); 组件更新,将新生成的虚拟dom与已有的真实dom的fiber链表对比; 遵循同级对比、深度对比原则,先依次找节点对比; 对比过程中,第一轮对比:按链表顺序对比,节点key值相

    2024年02月17日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包