Reac19 升级指南

Reactv19 已经发布 beta 版本,想要快速体验如何升级到 v19 版本尝鲜的朋友们可以查阅进行了解

前言

React 已于近日发布了 v19 的 beta 版本,同时为了帮助后续的 v19 升级,也同时发布了 v18.3.0的正式版, 与 v18.2 版本完全相同,但添加了弃用 API 的警告和其他为 React 19 所需的更改

安装

使用新版 JSX Transform

为了改善打包体积和可以在 JSX 文件中无需手动引入 React,在 2020 年 React 引入了新的 JSX Transform。如果在 React 19 中没有使用这个新的 JSX Transform 会有一个报错提示

如果已经使用了新版 JSX Transform 则可以忽略此步骤

安装最新版本的 React 和 ReactDom

npm install react@beta react-dom@beta

如果使用 TypeScript,则还需要更新相关类型包。等到 React 19 发布 release 版本后可以就像往常一样从@types/react@types/react-dom安装类型包。在当前 beta 版本中需要在package.json为类型包配置overrides 锁定版本以确保不同包中的类型是可用的

{
  "dependencies": {
    "@types/react": "npm:types-react@beta",
    "@types/react-dom": "npm:types-react-dom@beta"
  },
  "overrides": {
    "@types/react": "npm:types-react@beta",
    "@types/react-dom": "npm:types-react-dom@beta"
  }
}

Breaking changes

render 过程中的错误不再二次抛出

在之前的 React 版本中,渲染过程中抛出的错误会被捕获并重新抛出。在 DEV 模式下,我们还会记录到 console.error,导致出现重复的错误日志。

在 React 19 中,改进了错误处理方式,通过不重新抛出来减少重复信息:

  • 未捕获的错误:未被错误边界捕获的错误将调用给 window.reportError
  • 已捕获的错误:被错误边界捕获的错误将报告将调用给 console.error
    这个改变不应该影响大多数应用,但如果生产错误报告依赖于错误被重新抛出,则可能需要更新错误处理。为了支持这一点,React 19 添加了新的createRoothydrateRoot用于自定义错误处理:
const root = createRoot(container, {
  onUncaughtError: (error, errorInfo) => {
    // ... log error report
  },
  onCaughtError: (error, errorInfo) => {
    // ... log error report
  }
});

废弃 React API 移除

移除propTypes和函数组件的defaultProps

propTypes是用于运行时校验组件 props 的属性,在 Reactv15.5.0已经被标记为废弃,在 v19这个正式删除

另外函数组件的defaultProps也已经移除(使用 ES6 默认参数替代),由于 class 组件没有相应的 ES6 语法替代因此仍会保留

// Before
import PropTypes from 'prop-types';

function Heading({text}) {
  return <h1>{text}</h1>;
}
Heading.propTypes = {
  text: PropTypes.string,
};
Heading.defaultProps = {
  text: 'Hello, world!',
};
// After
interface Props {
  text?: string;
}
function Heading({text = 'Hello, world!'}: Props) {
  return <h1>{text}</h1>;
}
移除使用contextTypesgetChildContext的 Legacy Context

Legacy Context 在2018.10(v16.6.0)已被弃用

Legacy Context 仅适用于使用contextTypesgetChildContext API 的类组件,并由于易于忽略的微妙错误而被contextType替换。在 React 19 中,将删除 Legacy Context 以使 React 更小更快。仍在类组件中使用 Legacy Context,则需要迁移到新的contextType API:

// Before
import PropTypes from 'prop-types';

class Parent extends React.Component {
  //...
  static childContextTypes = {
    foo: PropTypes.string.isRequired,
  };

  getChildContext() {
    return { foo: 'bar' };
  }
  //...

  render() {
    return <Child />;
  }
}

class Child extends React.Component {
  //...
  static contextTypes = {
    foo: PropTypes.string.isRequired,
  };
  //...

  render() {
    return <div>{this.context.foo}</div>;
  }
}
// After

//...
const FooContext = React.createContext();
//....

class Parent extends React.Component {
  render() {
    return (
      <FooContext value='bar'>
        <Child />
      </FooContext>
    );
  }
}

class Child extends React.Component {
  //...
  static contextType = FooContext;
  //...

  render() {
    return <div>{this.context}</div>;
  }
}
移除字符串 refs

字符串 refs 在2018.3(v16.3.0)被弃用

在被替换为 ref 回调方式之前类组件支持字符串 refs,但存在多个缺点。在 React 19 中,将删除字符串引用以使 React 更简单易懂

// Before
class MyComponent extends React.Component {
  componentDidMount() {
    this.refs.input.focus();
  }

  render() {
    return <input ref='input' />;
  }
}

如果仍在使用类组件中的字符串引用,则需要迁移到 refs 回调的形式:

// After
class MyComponent extends React.Component {
  componentDidMount() {
    this.input.focus();
  }

  render() {
    return <input ref={input => this.input = input} />;
  }
}
移除模块模式工厂

模块模式工厂在2019.8(v16.9.0)被弃用。

// Before
function FactoryComponent() {
  return { render() { return <div />; } }
}

这种用法其实很少使用,支持它会使 React 比必要的更大和更慢。在 React 19 中,将删除对模块模式工厂的支持,需要迁移到常规函数:

// After
function FactoryComponent() {
  return <div />;
}
移除React.createFactory

createFactory 在2020.2(v16.13.0)已被弃用。

// Before
import { createFactory } from 'react';

const button = createFactory('button');

在 JSX 得到广泛支持之前使用 createFactory 很常见,但是现在已经可以用 JSX 替换。在 React 19 中,将删除 createFactory,需要迁移到 JSX

// After
const button = <button />;
移除react-test-renderer/shallow

在 React 18 中,更新了react-test-renderer/shallow并重新导出react-shallow-renderer。在 React 19 中,将删除react-test-render/shallow,而直接安装该软件包:

npm install react-shallow-renderer --save-dev
- import ShallowRenderer from 'react-test-renderer/shallow';
+ import ShallowRenderer from 'react-shallow-renderer';

废弃 ReactDOM API 移除

移除react-dom/test-utils
移除ReactDOM.render

ReactDOM.render在2022 年 3 月(v18.0.0)已被弃用。

// Before
import {render} from 'react-dom';
render(<App />, document.getElementById('root'));

在 React 19 中,将删除 ReactDOM.render,需要迁移到使用ReactDOM.createRoot

// After
import {createRoot} from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
移除ReactDOM.hydrate

ReactDOM.hydrate在2022 年 3 月(v18.0.0)已被弃用。在 React 19 中,将删除 ReactDOM.hydrate,需要迁移到使用ReactDOM.hydrateRoot

// Before
import {hydrate} from 'react-dom';
hydrate(<App />, document.getElementById('root'));

// After
import {hydrateRoot} from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);
移除unmountComponentAtNode

ReactDOM.unmountComponentAtNode在2022.3(v18.0.0)已被弃用。在 React 19 中需要迁移到使用hydrateRootcreateRoot对应的root.unmount()

// Before
unmountComponentAtNode(document.getElementById('root'));

// After
root.unmount();
移除ReactDOM.findDOMNode

ReactDOM.findDOMNode 在2018 年 10 月(v16.6.0)已被弃用

// Before
import {findDOMNode} from 'react-dom';

function AutoselectingInput() {
  useEffect(() => {
    const input = findDOMNode(this);
    input.select()
  }, []);

  return <input defaultValue="Hello" />;
}

可以使用 DOM 引用替换 ReactDOM.findDOMNode

// After
function AutoselectingInput() {
  const ref = useRef(null);
  useEffect(() => {
    ref.current.select();
  }, []);

  return <input ref={ref} defaultValue="Hello" />
}

新增废弃

废弃element.ref属性

从 React 19 开始,现在可以将ref作为函数组件的 prop 访问

如果直接访问 element.ref会出现警告

function MyInput({placeholder, ref}) {
  return <input placeholder={placeholder} ref={ref} />
}

//...
<MyInput ref={ref} />
image

新的函数组件将不再需要forwardRef,在未来的版本中,React 将弃用并删除forwardRef

但是传递给类的 refs 不会作为 props 传递,因为refs引用的是组件实例

废弃react-test-renderer

弃用react-test-rendererreact-test-renderer实现了自己的渲染器环境与用户使用的环境不匹配并依赖于 React 内部的实现细节

在 React 19 中,react-test-renderer会打印了一个弃用警告,并切换到并发渲染。建议将测试迁移到@testing-library/react@testing-library/react-native以获得更良好支持的测试体验

一些值得一提的变动

StrictMode 变化

React 19 包括了对 Strict Mode 的几个修复和改进。在开发中,当在 Strict Mode 下进行双重渲染时,useMemouseCallback将重用第一次渲染时的结果进行第二次渲染。已经兼容Strict Mode的组件也不会发生差异。与所有Strict Mode行为一样,这些功能为的是在开发过程中主动暴露组件中的错误,以便在它们被发布到生产环境之前修复。例如在开发过程中,Strict Mode将在初始挂载时双重调用ref回调函数,以模拟当挂载的组件被 Suspense 回退替换时的情况

移除 UMD 产物

UMD 曾经被广泛使用作为一种无需构建步骤即可加载 React 的便捷方式。现在有现代化的替代方案可以将模块作为脚本加载到 HTML 文档中。从 React 19 开始,React 将不再生成 UMD 构建,以减少其测试和发布过程的复杂性。

为了使用脚本标签加载 React 19,可以使用基于 ESM 的 CDN,例如esm.sh

<script type="module">
  import React from "https://esm.sh/react@19/?dev"
  import ReactDOMClient from "https://esm.sh/react-dom@19/client?dev"
  ...
</script>
依赖于 React 内部的库可能会影响升级

此版本包含对 React 内部的更改,可能会影响那些忽略 React 官方警告不要使用像SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED这样的内部机制的库。这些更改是为了实现 React 19 中的一些优化,但不会破坏遵循官方指南使用的库。

根据版本策略,这些更新不被列为重大更改,并且不包括有关如何升级它们的文档。建议删除依赖于内部机制的任何代码。

为了反映使用内部机制的影响,已将SECRET_INTERNALS后缀重命名为:

_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE

将来将使用更多方式阻止从 React 访问内部,以防止使用并确保用户不会被阻止升级

TypeScript 变化

移除废弃的 TypeScript 类型

根据 React 19 中删除的相关 API 清理了相关 TypeScript 类型。同时提供了一个types-react-codemod工具可以帮助迁移已有的类型

npx types-react-codemod@latest preset-19 ./path-to-app
ref 返回内容必须是清理函数

由于引入了ref清理函数,从ref回调返回任何其他内容现在将被 TypeScript 报错。修复方法通常是停止使用隐式返回:

- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />

原始代码返回HTMLDivElement的实例,TypeScript 无法确定是否清理函数。

useRef需要传递参数

通过更改类型使得 useRef 现在需要接收一个参数。这显著简化了它的类型签名。现在它的行为更像 createContext

// @ts-expect-error: Expected 1 argument but saw none
useRef();
// Passes
useRef(undefined);
// @ts-expect-error: Expected 1 argument but saw none
createContext();
// Passes
createContext(undefined);

现在也意味着所有的引用都是可变的。不再会遇到以下的问题,传递 number类型但是使用 null 初始化

// before
const ref = useRef<number>(null);

// Cannot assign to 'current' because it is a read-only property
ref.current = 1;

MutableRef现已弃用,建议使用单个RefObject类型,该类型将始终由useRef返回:

interface RefObject<T> {
  current: T
}

declare function useRef<T>: RefObject<T>

useRef 仍然有一个方便的重载 useRef(null),它自动返回 RefObject<T | null>。为了简化由于 useRef 所需参数的迁移,添加了一个方便的重载 useRef(undefined),它自动返回 RefObject<T | undefined>。

ReactElement类型变化

如果元素被标记为ReactElement,则ReactElementprops现在默认为unknown而不是any。如果向ReactElement传递类型参数则不会受到影响

type Example2 = ReactElement<{ id: string }>["props"];
//   ^? { id: string }

但是如果依赖默认设置,则需要处理unknown

type Example = ReactElement["props"];
//   ^? Before, was 'any', now 'unknown'
TypeScript 中的 JSX namespace 变化

类型中删除全局JSX命名空间转而使用React.JSX。防止全局类型的污染和不同 UI 库之间利用 JSX 产生冲突

现在,需要在declare module中的JSX命名空间的模块进行修改

// global.d.ts
+ declare module "react" {
    namespace JSX {
      interface IntrinsicElements {
        "my-element": {
          myElementProps: string;
        };
      }
    }
+ }

准确的模块说明符取决于在tsconfig.jsoncompilerOptions中指定的 JSX 运行时:

  • 对于"jsx": "react-jsx",将是 react/jsx-runtime
  • 对于 "jsx": "react-jsxdev",将是 react/jsx-dev-runtime
  • 对于 "jsx": "react""jsx": "preserve",它将是 react
更好的useReducer类型

useReducer类型推断得到了改善。然而这需要一个破坏性的变化,其中useReducer不再接受完整的reducer类型作为类型参数,而是需要接收StateAction的类型

新的最佳实践是不要向 useReducer 传递类型参数。

- useReducer<React.Reducer<State, Action>>(reducer)
+ useReducer(reducer)

这可能在边缘情况下无法正常工作,例如可以通过在元组中传递Action来显式输入状态和操作:

- useReducer<React.Reducer<State, Action>>(reducer)
+ useReducer<State, [Action]>(reducer)

如果内联定义 reducer,建议注释函数参数:

- useReducer<React.Reducer<State, Action>>((state, action) => state)
+ useReducer((state: State, action: Action) => state)

这也是如果将 reducer 移动到useReducer调用之外需要做的

const reducer = (state: State, action: Action) => state;

参考

React 19 Beta Upgrade Guide

React 19 Beta

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

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

相关文章

JavaEE初阶Day 15:文件IO(1)

目录 Day 15&#xff1a;文件IO&#xff08;1&#xff09;IO文件1. 路径2. 文件的分类3. 使用Java针对文件系统进行操作3.1 属性3.2 构造方法3.3 方法 Day 15&#xff1a;文件IO&#xff08;1&#xff09; IO I&#xff1a;Input输入 O&#xff1a;Output输出 输入输出规则…

【golang-ent】go-zero框架 整合 ent orm框架实现一对一 一对多 多种姿势查询方式

一、ent的 O2O 问题 官方文档如下: https://entgo.io/zh/docs/schema-edges#o2o-same-type 1、ent O2O问题 官方提供了三种 one2one的方式,可以看到他全部使用了 mysql的 foregionKey 的方式进行关联,虽然举例了单表和双表的不同使用方式,但是我们实际使用mysql中是不创建…

深度解析 Spring 源码:探寻Bean的生命周期

文章目录 一、 Bean生命周期概述二、Bean生命周期流程图三、Bean生命周期验证3.1 代码案例3.2 执行结果 四、Bean生命周期源码4.1 setBeanName()4.2 setBeanFactory()4.3 setApplicationContext()4.4 postProcessBeforeInitialization()4.5 afterPropertiesSet()4.6 postProces…

银行数字化转型导师坚鹏:银行数字化转型5大战略定位

银行数字化转型必须建立清晰的战略定位&#xff0c;可以从以下5个方面建立&#xff0c;使广大银行员工明白银行数字化转型的重要性。 1.国家战略落地的重要抓手 银行是中国金融体系的核心&#xff0c;银行是做好“科技金融、绿色金融、普惠金融、养老金融和数字金融‘五篇大文…

【c++】继承学习(二):探索 C++ 中派生类的默认机制与静态成员共享

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 目录 1.派生类的默认成员函数2.继承与友元3.继承与静态成员 朋友们大家好&#xff0c;本篇文章我们来学习继承的第二部分 1.派生类的默认成员函数 来看下面的类&#xff1a; class Person…

【自留】运行一个开源项目

运行一个开源项目 首先是运行起来 1. 拿到地址 拿到你想要的项目的地址 2. 克隆 打开编辑器 VSCode &#xff0c;创建一个放项目的文件夹&#xff0c;控制台输入以下代码克隆项目 git clone 克隆地址gitee克隆地址在这看&#xff1a; github上项目的话&#xff0c;在这…

【python的魅力】:教你如何用几行代码实现文本语音识别

文章目录 引言一、运行效果二、文本转换为语音2.1 使用pyttsx32.2 使用SAPI实现文本转换语音2.3 使用 SpeechLib实现文本转换语音 三、语音转换为文本3.1 使用 PocketSphinx实现语音转换文本 引言 语音识别技术&#xff0c;也被称为自动语音识别&#xff0c;目标是以电脑自动将…

SSM+Vue+小程序+基于微信小程序的高校学生事务管理系统

项目配合学校日常生活通知&#xff0c;考试等管理需要&#xff0c;开发学校事务管理系统&#xff0c;maven管理依赖&#xff0c;mybatis处理数据库交互 学校管理 学院管理 班级管理 年级管理 教师管理 通知公告管理 学生资料管理 待办事项管理 教务处通知管理 讲座通…

【Conda】解决无名虚拟环境问题

文章目录 问题描述&#xff1a;无名虚拟环境解决步骤1 添加虚拟环境目录到envs步骤2 成功命名 问题描述&#xff1a;无名虚拟环境 如果不指定创建目录&#xff0c;默认创建在C盘用户目录下&#xff0c;这应该是很多人不愿意的吧。 指定目录创建虚拟环境命令如下&#xff1a; …

vector的使用

1.构造函数 void test_vector1() {vector<int> v; //无参的构造函数vector<int> v2(10, 0);//n个value构造&#xff0c;初始化为10个0vector<int> v3(v2.begin(), v2.end());//迭代器区间初始化,可以用其他容器的区间初始化vector<int> v4(v3); //拷贝…

基于yolov8的苹果腐败检测系统,系统既支持图像检测,也支持视频和摄像实时检测(pytorch框架)【python源码+UI界面+功能源码详解】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于yolov8的苹果腐败检测系统&#xff0c;系统既支持图像检测&#xff0c;也支持视频和摄像实时检测_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov8的苹果腐败检测系统是在pytorc…

STM32 F103C8T6学习笔记17:类IIC通信(SMBus协议)—MLX90614红外非接触温度计

今日学习配置MLX90614红外非接触温度计 与 STM32 F103C8T6 单片机的通信 文章提供测试代码讲解、完整工程下载、测试效果图 本文需要用到的大概基础知识&#xff1a;1.3寸OLED配置通信显示、IIC通信、 定时器配置使用 这里就只贴出我的 OLED驱动方面的网址链接了&#xff1a…

Golang数组与切片

文章目录 数组数组介绍数组的定义方式访问与修改数组元素遍历数组元素数组指针 切片切片介绍切片的定义方式访问与修改切片元素添加切片元素切片的拷贝遍历切片元素string的切片 数组 数组介绍 数组介绍 在Go中&#xff0c;数组是一个由固定长度的特定类型元素组成的序列&…

[Algorithm][队列][宽搜BFS][N叉树的层序遍历][二叉树的锯齿形层序遍历][二叉树最大宽度][在每个树行中找最大值]详细讲解

目录 1.N 叉树的层序遍历1.题目链接2.算法思路详解3.代码实现 2.二叉树的锯齿形层序遍历1.题目链接2.算法原理详解3.代码实现 3.二叉树最大宽度1.题目链接2.算法原理详解3.代码实现 4.在每个树行中找最大值1.题目链接2.算法原理详解3.代码实现 1.N 叉树的层序遍历 1.题目链接 …

数据结构之链表深度讲解

小伙伴们&#xff0c;大家好呀&#xff0c;上次听我讲完顺序表想必收获不少吧&#xff0c;嘿嘿&#xff0c;这篇文章你也一样可以学到很多&#xff0c;系好安全带&#xff0c;咱们要发车了。 因为有了上一次顺序表的基础&#xff0c;所以这次我们直接进入正题&#xff0c;温馨…

Activiti7 开发快速入门【2024版】

记录开发最核心的部分&#xff0c;理论结合业务实操减少废话&#xff0c;从未接触工作流快速带入开发。假设你是后端的同学学过JAVA和流程图&#xff0c;则可以继续向后看&#xff0c;否则先把基础课程书准备好先翻翻。 为什么要工作流 比起直接使用状态字段&#xff0c;工作…

【 书生·浦语大模型实战营】作业(六):Lagent AgentLego 智能体应用搭建

【 书生浦语大模型实战营】作业&#xff08;六&#xff09;&#xff1a;Lagent & AgentLego 智能体应用搭建 &#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方…

【机器学习】集成方法---Boosting之AdaBoost

一、Boosting的介绍 1.1 集成学习的概念 1.1.1集成学习的定义 集成学习是一种通过组合多个学习器来完成学习任务的机器学习方法。它通过将多个单一模型&#xff08;也称为“基学习器”或“弱学习器”&#xff09;的输出结果进行集成&#xff0c;以获得比单一模型更好的泛化性…

上海计算机学会2021年1月月赛C++丙组T2康托表

题目背景 康托是一名数学家&#xff0c;他证明了一个重要的定理&#xff0c;需要使用一张表&#xff1a; 这个表的规律是&#xff1a; 从上到下&#xff1a;每一行的分子依次增大&#xff1b;从左到右&#xff1a;每一列的分母依次增大。 康托以一种不重复、不遗漏的方式&am…

【深耕 Python】Quantum Computing 量子计算机(1)图像绘制基础

一、绘制静止图像 使用matplotlib库绘制函数图像y sin(pi * x): import math import matplotlib.pyplot as pltx_min -2.0 x_max 2.0N 1000x1 [] y1 []for i in range(N 1):x x_min (x_max - x_min) * i / Ny math.sin(math.pi * x)x1.append(x)y1.append(y)plt.xl…