React19学习-初体验
升级react19版本
- 安装
npm install react@beta react-dom@beta
如果使用ts则需要在package.json中添加。等正式版发布直接可以使用@types/react
了
"overrides": {"@types/react": "npm:types-react@beta","@types/react-dom": "npm:types-react-dom@beta"}
官方文档
初始化项目
npm create vite
选vanilla 和 ts- 配置vite.config.ts
import {defineConfig} from "vite";
import react from '@vitejs/plugin-react';
/** @type {import('vite').UserConfig} */
export default {plugins:[react()]
}
- 安装依赖,如下
package.json
文件
{"name": "react19_exp","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite","build": "tsc && vite build","preview": "vite preview"},"devDependencies": {"@types/node": "^20.12.10","@vitejs/plugin-react": "^4.2.1","typescript": "^5.2.2","vite": "^5.2.0"},"dependencies": {"@types/react": "npm:types-react@beta","@types/react-dom": "npm:types-react-dom@beta","react": "^19.0.0-beta-b498834eab-20240506","react-dom": "^19.0.0-beta-b498834eab-20240506"},"overrides": {"@types/react": "npm:types-react@beta","@types/react-dom": "npm:types-react-dom@beta"}
}
- 配置tsconfig.json
{"compilerOptions": {"target": "ES2020","useDefineForClassFields": true,"module": "ESNext","lib": ["ES2020", "DOM", "DOM.Iterable"],"skipLibCheck": true,/* Bundler mode */"moduleResolution": "bundler","allowImportingTsExtensions": true,"resolveJsonModule": true,"isolatedModules": true,"noEmit": true,/* Linting */"strict": true,"noUnusedLocals": true,"noUnusedParameters": true,"noFallthroughCasesInSwitch": true,"jsx": "react-jsx"},"include": ["src"],"references": [{ "path": "./tsconfig.node.json" }]/*tsconfig.node.json{"compilerOptions": {"composite": true,"skipLibCheck": true,"module": "ESNext","moduleResolution": "bundler","allowSyntheticDefaultImports": true,"strict": true},"include": ["vite.config.ts"]}
*/
}
- 之后将项目中的ts可以改为tsx启动项目即可
react19新特性体验
表单相关Hooks
状态突变
什么是状态突变?状态突变是指系统或对象的状态在某个时间点发生突然、不可预测的变化。
例如,当用户提交表单以更改其姓名时,将发出 API 请求,然后处理响应。过去,需要手动处理挂起状态、错误、乐观更新和顺序请求。过去使用方式代码示例
function UpdateName({}) {const [name, setName] = useState("");const [error, setError] = useState(null);const [isPending, setIsPending] = useState(false);const handleSubmit = async () => {setIsPending(true);const error = await updateName(name);setIsPending(false);if (error) {setError(error);return;} redirect("/path");};return (<div><input value={name} onChange={(event) => setName(event.target.value)} /><button onClick={handleSubmit} disabled={isPending}>Update</button>{error && <p>{error}</p>}</div>);
}
现在React提供了useTransition
钩子,19使用示例
import {useState, useTransition} from "react";function updateName(name:string):Promise<string>{return new Promise((r)=>{setTimeout(()=>{if (!name)r("name不能为空")},2000)})
}export default ()=>{const [name, setName] = useState("");const [error, setError] = useState<string|null>(null);const [isPending, startTransition] = useTransition();const handleSubmit = () => {startTransition(async () => {const error = await updateName(name);if (error) {setError(error);return;}})};const renderLoading = ()=>{return <div className="loader"></div>}return (<div><input value={name} onChange={(event) => setName(event.target.value)}/>{isPending && renderLoading()}<button onClick={handleSubmit} disabled={isPending}>Update</button>{error && <p>{error}</p>}</div>)
}
效果展示
表单提交状态+行为useActionState
useActionState
接受一个函数(“Action”),并返回一个包装的 Action
进行调用。调用包装的 Action 时, useActionState
将 Action 的最后一个结果返回为data
作为state
的值 ,并将 Action
的挂起状态返回 pending
。
//函数签名
useActionState<State,Payload>(action: (state: Awaited<State>,payload: Payload) => State | Promise<State>,//表单提交行为initialState: Awaited<State>, // 初始表单的值permalink?: string, // 目前不太了解,推测是表单提交后达到某个条件跳转到该链接上。有明白的小伙伴可以评论区留言
): [state: Awaited<State>, dispatch: (payload: Payload) => void, isPending: boolean];
示例
import {useActionState, useEffect} from "react";
function updateName(name:string):Promise<string>{return new Promise((r)=>{setTimeout(()=>{if (!name)r("name不能为空")r(name)},2000)})
}
export default ()=>{const [state, submitAction, isPending] = useActionState<string>(async (previousState:string, formData) => {const state = await updateName(formData.get("name"));// handle successreturn state;},"初始name值",);return (<form action={submitAction}><input type="text" name="name" /><button type="submit" disabled={isPending}>Update</button>{isPending && <div className="loader"></div>}{state && <p style={{color:"green"}}>{state}</p>}</form>);
}
获取父组件表单状态useFormStatus
该Hooks为Form下面的子组件提供form状态信息,让我们不依赖父组件注入的Context就能获取到父组件的表单状态。
子组件
import {useFormStatus} from "react-dom";export default ()=>{const {pending} = useFormStatus();return <button type="submit" disabled={pending} >提交表单</button>
}
父组件部分代码展示
<form action={submitAction}><input type="text" name="name" /><ExpUseFormStatus></ExpUseFormStatus>{isPending && <div className="loader"></div>}{state && <p style={{color:"green"}}>{state}</p>}</form>
效果展示
乐观更新useOptimistic
有时候有些结果99%会成功,我们希望让用户尽快看到页面展示效果。可以采用该钩子。
子组件
import {useOptimistic} from "react";
interface Props{currentName:stringonUpdateName:(name:string)=>void
}
function updateName(name:string):Promise<string>{return new Promise((r)=>{setTimeout(()=>{if (!name)r("name不能为空")r(name)},2000)})
}
export default({currentName, onUpdateName}:Props)=> {const [optimisticName, setOptimisticName] = useOptimistic(currentName);const submitAction = async (formData: { get: (arg0: string) => any; }) => {const newName = formData.get("name");setOptimisticName(newName);const updatedName = await updateName(newName);onUpdateName(updatedName);};return (<form action={submitAction}><p>Your name is(currentName):<span style={{color:"green"}}>{currentName}</span> </p><p>Your name is(optimisticName): {optimisticName}</p><p><label>Change Name:</label><inputtype="text"name="name"disabled={currentName !== optimisticName}/></p><button type="submit">提交</button></form>);
}
父组件
export default ()=>{const [currentName, setCurrentName] = useState("fancy")return (<><ExpUseOptimistic currentName={currentName} onUpdateName={(name)=>setCurrentName(name)}></ExpUseOptimistic></>)
}
结果展示
其他
use
use Hook让我们可以读取Context和Promise的值并且可以在循环和条件语句(如 if)中调用 use。但需要注意的是,调用 use 的函数仍然必须是一个组件或 Hook。
import { use } from 'react';function MessageComponent({ messagePromise }) {const message = use(messagePromise);const theme = use(ThemeContext);// ...
ref
以后不需要forward ref做转发了
function MyInput({placeholder, ref}) {return <input placeholder={placeholder} ref={ref} />
}<MyInput ref={ref} />
ref的清理函数,当组件卸载时,React 将调用从回调返回的 ref 清理函数。这适用于 DOM 引用、类组件引用和 useImperativeHandle .
<inputref={(ref) => {// ref created// NEW: return a cleanup function to reset// the ref when element is removed from DOM.return () => {// ref cleanup};}}
/>
Context 不再需要<Context.Provider>
const ThemeContext = createContext('');function App({children}) {return (<ThemeContext value="dark">{children}</ThemeContext>);
}
支持在组件中编写Meta标签
当 React 渲染这个组件时,它会看到 <title> <link>
和 <meta>
标签,并自动将它们提升到文档 <head>
部分。通过本机支持这些元数据标记,我们能够确保它们适用于仅限客户端的应用、流式处理 SSR 和服务器组件。
function BlogPost({post}) {return (<article><h1>{post.title}</h1><title>{post.title}</title><meta name="author" content="Josh" /><link rel="author" href="https://twitter.com/joshcstory/" /><meta name="keywords" content={post.keywords} /><p>Eee equals em-see-squared...</p></article>);
}
支持预加载资源
文档
在初始文档加载和客户端更新期间,告知浏览器可能需要尽早加载的资源可能会对页面性能产生巨大影响。React 19 包含许多用于加载和预加载浏览器资源的新 API,以便尽可能轻松地构建出色的体验,而不会因资源加载效率低下而受到阻碍。
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
function MyComponent() {preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerlypreload('https://.../path/to/font.woff', { as: 'font' }) // preloads this fontpreload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheetprefetchDNS('https://...') // when you may not actually request anything from this hostpreload("https://example.com/font.woff2", {as: "font"});//加载字体preload("https://example.com/style.css", {as: "style"});//预加载css文件preconnect('https://...') // when you will request something but aren't sure what}
这些会被转化为以下形式
<head><!-- links/scripts are prioritized by their utility to early loading, not call order --><link rel="prefetch-dns" href="https://..."><link rel="preconnect" href="https://..."><link rel="preload" as="font" href="https://.../path/to/font.woff"><link rel="preload" as="style" href="https://.../path/to/stylesheet.css"><script async="" src="https://.../path/to/some/script.js"></script></head>
我们可以在渲染时和事件处理中进行预加载。
如果知道组件或其子组件将使用特定资源,那么在渲染组件时调用 preload。
在渲染时示例
import { preload } from 'react-dom';function AppRoot() {preload("https://example.com/font.woff2", {as: "font"});// ……
}
时间中
import { preload } from 'react-dom';function CallToAction() {const onClick = () => {preload("https://example.com/wizardStyles.css", {as: "style"});startWizard();}return (<button onClick={onClick}>Start Wizard</button>);
}
相关文章:

React19学习-初体验
升级react19版本 安装 npm install reactbeta react-dombeta如果使用ts则需要在package.json中添加。等正式版发布直接可以使用types/react了 "overrides": {"types/react": "npm:types-reactbeta","types/react-dom": "npm:ty…...

【UE5】数字人基础
这里主要记录一下自己在实现数字人得过程中涉及导XSens惯性动捕,视频动捕,LiveLinkFace表捕,GRoom物理头发等。 一、导入骨骼网格体 骨骼网格体即模型要在模型雕刻阶段就要雕刻好表捕所需的表情体(blendshape),后面表捕的效果直…...
OSTEP Projects:KV
本文将介绍操作系统导论(Operating Systems: Three Easy Pieces)作者所开源的操作系统相关课程项目 的 KV 部分,包含个人的代码实现和设计思路。 思路 题目要求实现一个最简单的数据库,以支持数据的持久化。 每个操作由格式为 o…...

JAVA学习笔记(第三周)
文章目录 继承概述使用场景继承的特点子类继承的内容成员变量访问特点成员方法访问特点方法的重写构造方法this super 多态多态的表现形式多态的前提成员变量和方法调用instanceof优势弊端 包包名的规则全类名final常量 权限修饰符代码块 继承 概述 继承就是子类继承父类的特征…...

linux 内核驱动 -- reboot -f 导致内核死机 而 reboot则不会引起问题
问题描述,定于与解决:...

【vue-echarts】 报错问题解决 “Error: Component series.pie not exists. Load it first.“
目录 问题描述解决【解决1】【解决2】 问题描述 使用 vue-echarts 时导入的文件 import VChart from vue-echarts/components/ECharts import echarts/lib/chart/line import echarts/lib/chart/bar import echarts/lib/chart/pie import echarts/lib/component/legend impor…...

MySQL慢查询SQL优化
一、慢查询日志 描述:通过慢查询日志等定位那些执行效率较低的SQL语句 查看 # 慢查询是否开启 show variables like slow_query_log%; # 慢查询超时时间 show variables like long_query_time%;执行SQL 开启慢查询日志 set global slow_query_log ON;设置慢查…...
【嵌入式DIY实例】-DDS信号生成器
DDS信号生成器 文章目录 DDS信号生成器1、AD9805介绍2、硬件准备与接线3、代码实现在本文中,将详细介绍如何使用AD9850来搭建一个简易的DDS(Direct Digital signal )信号生成器。 1、AD9805介绍 AD9850是一款高度集成的器件,采用先进的DDS技术,内置一个高速、高性能数模转…...
java设计模式四 桥接模式
桥接模式关注于将抽象部分与实现部分分离,使它们可以独立变化。它通过在抽象和实现之间建立一个桥梁来实现这一目的。这种设计模式属于结构型模式。 假设我们要设计一个图形编辑器,其中图形(如圆形、正方形)可以有不同的颜色填充…...

《Python编程从入门到实践》day24
# 昨日知识点学习 创建外星人从一个到一行 # 主程序snipdef _create_fleet(self):"""创建外星人群"""# 创建一个外星人并计算一行可容纳多少个外星人# 外星人的间距为外星人的宽度alien Alien(self)alien_width alien.rect.widthavailable_sp…...

【hackmyvm】 Animetronic靶机
靶机测试 arp-scanporturl枚举exiftool套中套passwordsudo 提权 arp-scan arp-scan 检测局域网中活动的主机 192.168.9.203 靶机IP地址port 通过nmap扫描,获取目标主机的端口信息 ┌──(root㉿kali)-[/usr/share/seclists] └─# nmap -sT -sV -O 192.16…...

[附源码]石器时代_恐龙宝贝内购版_三网H5手游_带GM工具
石器时代之恐龙宝贝内购版_三网H5经典怀旧Q萌全网通手游_Linux服务端源码_视频架设教程_GM多功能授权后台_CDK授权后台 本教程仅限学习使用,禁止商用,一切后果与本人无关,此声明具有法律效应!!!࿰…...

RS2255XN功能和参数介绍及PDF资料
RS2255XN是一款由Runic(润石)公司生产的模拟开关。以下是关于RS2255XN的一些技术参数和特点: 封装:MSOP-10 电源电压范围:2.5V至5.5V 工作温度范围:-40C至125C 类型:模拟开关 品牌:R…...
设计模式——外观模式(Facade)
外观模式(Facade Pattern) 是一种结构型设计模式,它为一个子系统中的一组接口提供一个统一的高层接口,使得子系统更加容易使用。这种类型的设计模式属于结构型模式,它向客户端提供了一个接口,隐藏了子系统的…...
【linux软件基础知识】Linux 中的普通进程的调度机制
活动集Active processes和过期集Expired processes 为了实现静态优先级较低的进程没有完全锁定并有机会运行,Linux 调度程序维护两个不相交的可运行进程集:活动集和过期集。 此机制是完全公平调度程序 (CFS) 算法的一部分。 以下是这两组的工作原理: 活动集Active proces…...

keil5软件安装教程(MDKv5.39)
keil5软件安装分为三部分: 目录 1.安装mdk 2.激活mdk 3.安装STM32芯片包 1.安装mdk 安装包链接:链接:https://pan.baidu.com/s/1PZoGhzI5Y19ROv7xe9QJKA?pwdgt3s 提取码:gt3s 1、下载keil5的压缩包并解压,鼠…...

改变视觉创造力:图像合成中基于样式的生成架构的影响和创新
原文地址:revolutionizing-visual-creativity-the-impact-and-innovations-of-style-based-generative 2024 年 4 月 30 日 介绍 基于风格的生成架构已经开辟了一个利基市场,它将机器学习的技术严谨性与类人创造力的微妙表现力融为一体。这一发展的核…...

【LAMMPS学习】八、基础知识(5.8)LAMMPS 中热化 Drude 振荡器教程
8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…...

基于SpringBoot的全国风景区WebGIS按省展示实践
目录 前言 一、全国风景区信息介绍 1、全国范围内数据分布 2、全国风景区分布 3、PostGIS空间关联查询 二、后台查询的设计与实现 1、Model和Mapper层 2、业务层和控制层设计 三、WebGIS可视化 1、省份范围可视化 2、省级风景区可视化展示 3、成果展示 总结 前…...

深入理解网络原理3----TCP核心特性介绍(上)【面试高频考点】
文章目录 前言TCP协议段格式一、确认应答【保证可靠性传输的机制】二、超时重传【保证可靠性传输的机制】三、连接管理机制【保证可靠性传输的机制】3.1建立连接(TCP三次握手)---经典面试题3.2断开连接(四次挥手)3.3TCP状态转换 四…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...

Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...