React19学习-初体验

升级react19版本

  1. 安装
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"}

官方文档

初始化项目

  1. npm create vite 选vanilla 和 ts
  2. 配置vite.config.ts
import {defineConfig} from "vite";
import react from '@vitejs/plugin-react';
/** @type {import('vite').UserConfig} */
export default {plugins:[react()]
}
  1. 安装依赖,如下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"}
}
  1. 配置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"]}
*/
}
  1. 之后将项目中的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>);
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【LLM 论文】Chain-of-Verification:通过验证链来减少 LLM 幻觉

论文&#xff1a;Chain-of-Verification Reduces Hallucination in Large Language Models ⭐⭐⭐ arXiv:2309.11495 论文速读 LLM 由于不可避免地会产生幻觉&#xff0c;现有的研究主要鼓励 LLM 在产生 response 之前生成内部思想的推理链&#xff0c;或者通过 self-critique…

PG 全页写

1.什么是全页写 修改一个块的时候&#xff0c;把块读到内存中&#xff0c;commit后,WAL写进程会触发写&#xff0c;把修改的块写到WAL日志文件&#xff0c;如果再往这个块中插入一条数据&#xff0c;数据缓冲区里面的块有两条数据了&#xff0c;再次commit后&#xff0c;PG会把…

车载测试系列:自动驾驶中间件SOME/IP

一、以太网引入汽车 2004年&#xff0c;宝马汽车的OBD诊断口采用的是高速CAN总线&#xff0c;速率为500kbit/s&#xff0c;除去CAN协议本身的开销&#xff0c;通过OBD口升级控制器的净升级速度降到200kbit/s。预计到2008年&#xff0c;软件更新的数据量会达到1GB&#xff0c;按…

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024)

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024) 会议简介 2024国际化学材料、清洁能源和生物技术大会&#xff08;ICCMCEB2024&#xff09;将在长沙隆重举行。本次会议旨在汇聚来自世界各地的化学材料、清洁能源和生物技术领域的专家学者&#xff0c;共同探…

【计算机毕业设计】springboot合庆镇停车场车位预约系统

本系统为用户而设计制作合庆镇停车场车位预约系统&#xff0c;旨在实现合庆镇停车场车位预约智能化、现代化管理。本合庆镇停车场车位预约管理自动化系统的开发和研制的最终目的是将合庆镇停车场车位预约的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代…

vue----- watch监听$attrs 的注意事项

目录 前言 原因分析 解决方案 总结 前言 在 Vue 开发过程中&#xff0c;如遇到祖先组件需要传值到孙子组件时&#xff0c;需要在儿子组件接收 props &#xff0c;然后再传递给孙子组件&#xff0c;通过使用 v-bind"$attrs" 则会带来极大的便利&#xff0c;但同时…

【进程替换】多进程程序替换原理 | 进程程序替换函数 | execlexecv | execlpexecvp

目录 多进程程序替换 多进程程序替换原理 进程程序替换函数详解 execl&execv execlp&execvp execle&execvpe execve 多进程程序替换 我们想要进程替换的同时不影响旧的进程&#xff08;使用多进程版&#xff09;fork创建子进程&#xff0c;让子进程去替换执…

大模型在智能客服领域的应用思考

前言 随着大模型技术的飞速发展,其在商业化应用的落地实践上仍面临着挑战,不论是面向C端用户的付费服务模式,还是面向B端企业的业务赋能策略,目前都尚未形成成熟且清晰的商业模式。 在我所专注的智能客服领域,作为人工智能落地应用的前沿阵地,我深刻感受到大模型的生成…

面试集中营—Redis面试题

一、Redis的线程模型 Redis是基于非阻塞的IO复用模型&#xff0c;内部使用文件事件处理器&#xff08;file event handler&#xff09;&#xff0c;这个文件事件处理器是单线程的&#xff0c;所以Redis才叫做单线程的模型&#xff0c;它采用IO多路复用机制同时监听多个socket&a…

gorm-sharding分表插件升级版

代码地址&#xff1a; GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充&#xff0c;带来的额外开销极小。对开发者友好、透明&#xff0c;使用上与普通 SQL、Gorm 查询无差别.解决了原生s…

爬虫学习--5.xpath数据解析

xpath是XML路径语言&#xff0c;它可以用来确定xml文档中的元素位置&#xff0c;通过元素路径来完成对元素的查找。HTML就是XML的一种实现方式&#xff0c;所以xpath是一种非常强大的定位方式。 基本概念 XPath&#xff08;XML Path Language&#xff09;是一种XML的查询语言…

03.进程

并发 进程是运行起来的程序&#xff0c;是OS&#xff08;操作系统&#xff09;进行资源分配和调度的基本单位。 当只有一个cpu&#xff0c;进程遇到阻塞事件的时候&#xff08;可能是要去磁盘中读取数据&#xff09;&#xff0c;我们知道cpu的执行速度和磁盘的IO速度相差特别大…

传感器—超声波雷达

声波技术 在讲述超声波雷达之前&#xff0c;先了解一下声波的概念以及超声波和声波之间的关系 什么是声波&#xff1f; 声波是物体机械振动状态&#xff08;或能量&#xff09;的传播形式。所谓振动是指物质的质点在其平衡位置附近进行的往返运动形式&#xff0c;这种振动状…

2023盘古石晋级赛 移动终端取证 WP

9. 根据容恨寒的安卓手机分析&#xff0c;MAC的开机密码是[答案&#xff1a;asdcz] 到这里火眼就寄了&#xff0c;盘古石 启动&#xff01; 10. 根据容恨寒的安卓手机分析&#xff0c;苹果手机的备份密码前4位是[答案&#xff1a;1234] 11. 根据魏文茵苹果手机分析&#xff0c…

找不到vcruntime140_1.dll怎么办,介绍5种简单有效的解决方法

当您的电脑系统提示找不到vcruntime140_1.dll文件时&#xff0c;这通常意味着系统在尝试运行某个应用程序或游戏时&#xff0c;无法定位到这个至关重要的动态链接库&#xff08;DLL&#xff09;文件。此情况可能源于几个不同的原因&#xff0c;包括但不限于&#xff1a;文件被误…

电信网关配置管理系统 rewrite.php 文件上传致RCE漏洞复现

0x01 产品简介 中国电信集团有限公司(英文名称“China Telecom”、简称“中国电信”)成立于2000年9月,是中国特大型国有通信企业、上海世博会全球合作伙伴。电信网关配置管理系统是一个用于管理和配置电信网络中网关设备的软件系统。它可以帮助网络管理员实现对网关设备的远…

三分钟上手安全渗透系统Kali Linux

kali linux系统集成了常用的安全渗透工具&#xff0c;省去了安装工具的时间&#xff0c;做安全相关的工作是非常推荐使用的。 安装Kalii Linux 安装系统 一般使用虚拟机进行安装&#xff0c;Kali Linux基于Debian内核&#xff0c;虚拟机的操作系统选择Debian 7.x 64 选择系统…

C++入门 string类(第二章):string类对象的容量操作

文章目录 &#x1f680;1. string类对象的容量操作⚡️1.1 size⚡️1.2 capacity⚡️1.3 max_size⚡️1.4 resize⚡️1.5 reserve⚡️1.6 clear⚡️1.7 empty &#x1f680;2. string类对象访问元素⚡️2.1 at⚡️2.2 back 与 front &#x1f680;3. string类对象的字符串操作&…

嵌入式学习<1>:建立工程、GPIO和keil仿真

嵌入式学习_part1 本部分笔记用于学习记录&#xff0c;笔记源头 >>b站江科大_STM32入门教程_新建工程 建立工程、GPIO 开发环境&#xff1a;keil MDK、STM32F103C8T6 1 &#xff09;建立工程 &#xff08;1&#xff09;基于寄存器开发、基于标准库 或者 基于HAL库开…

海睿思受邀参加 “走进中节能”研习交流,探索新能源数据治理的创新路径

近日&#xff0c;OceanMind海睿思参加由江苏省企业信息化协会&#xff08;以下简称“苏信会”&#xff09;主办的“走进中节能太阳能科技&#xff08;镇江&#xff09;有限公司”研习交流活动。 海睿思与苏美达、远东控股、隆基乐叶、固德威、上能电气等40多位来自制造业领域的…