React 19新特性和更新介绍 01 - 新特性
React 19:新特性和更新介绍
React 19 于 2024 年 4 月 25 日正式发布,标志着一个重要的里程碑。
此版本带来了各种新功能和改进,以增强开发人员体验和应用程序性能。
React 19 新特性
1. 服务器组件(Server Components) - 主要更新
Server Components 是 React 19 中最大的变化之一,它提供了一种在服务器端渲染组件的新方法,并提供了更快、更高效的用户体验。
- 缩短初始页面加载时间:通过在服务器端渲染组件,React 19 减少了发送到客户端的 JavaScript 数量(只需返回渲染后的结果),从而加快了初始加载时间。在将页面发送到客户端之前,还可以在服务器上从数据库中对数据进行提取。
- 增强的代码可移植性:服务器组件允许开发人员编同时可以在服务器和客户端上运行的组件,从而减少重复,提高可维护性,并更轻松地在代码库中共享逻辑。
- 更好的 SEO:组件的服务器端渲染可确保发送到客户端的 HTML 已填充内容,从而使搜索引擎更容易抓取和索引网站。
例子:
// Users.server.jsx
// Server Component: Fetches data and returns JSX
export default async function Users() {
const res = await fetch("https://api.example.com/users");
const users = await res.json();
return (
<div>
<h1>Users</h1>
{users.map((user) => (
<div key={user.id}>
<h2>{user.name}</h2>
<p>{user.role}</p>
</div>
))}
</div>
);
}
2. 新指令: 'use client'
和 'use server'
随着 Server Components 的引入,React 19 引入了两个新指令来帮助开发人员管理代码的执行位置。
'use client'
: 此指令标记应在客户端上运行的代码。由于组件默认是在服务器端运行的,因此在使用钩子(hooks)实现交互和状态时,您可以在端组件中添加此指令。'use server'
: 标记函数在服务端上执行。不需对 Server Components 显式使用'use server'
指令。只需添加到 Server Actions 即可。对于特定于服务器的代码,可以使用仅限服务器的 npm 包。
3. 增强表单处理和状态管理
Actions 是 React 19 中的一个新概念,它简化了处理表单提交和与 React 并发功能集成的过程。
以下是 Actions 如何改善开发:
- 简化的事件处理:Actions 可以替代传统的事件处理程序,例如 onSubmit,从而允许将 FormData 直接传递给操作函数,而无需手动解析。
- Server Actions:这些操作使 Client Components 能够调用在服务器端执行异步函数,从而使得访问文件系统或查询数据库等任务更容易,而无需自定义 API 端点。
示例:
// actions.js
'use server';
export async function create() {
// 实现插入数据库的代码逻辑
}
"use client";
import { create } from "./actions";
export default function TodoList() {
return (
<>
<h1>Todo List</h1>
<form action={create}>
<input type="text" name="item" placeholder="Add todo..." />
<button type="submit">Add</button>
</form>
</>
);
}
4. 新的钩子函数: useActionState
React 19 引入了一个新的钩子 useActionState,专门用于简化处理 Actions 中的数据变化和状态更新。它通过管理待处理状态并返回操作的最终结果来简化流程。
主要功能
- 管理待处理状态:useActionState 在操作期间自动跟踪并更新待处理状态,从而无需在组件中手动更新。
- 返回结果和待处理状态:钩子返回一个包含两个值的数组:操作的最终结果(例如,错误消息或成功数据)以及指示操作是否仍处于待处理状态的布尔值。
- 组合动作:动作可以组合,这意味着多个动作可以链接在一起。 useActionState 处理执行顺序和最终状态更新。
示例:
const [error, submitAction, isPending] = useActionState(
async (_, newName) => await updateName(newName),
null
);
return (
<form onSubmit={submitAction}>
<input /* ... */ />
<button disabled={isPending}>{isPending ? "Saving..." : "Save"}</button>
{error && <p>{error}</p>}
</form>
);
5. 新的钩子函数: useFormStatus
React 19 引入了一个新的钩子 useFormStatus,旨在访问子组件中父表单的信息。 这在设计系统中特别有用,因为组件需要与表单的状态进行交互,而无需进行大量的 prop 钻取。
主要功能
- 访问父表单状态:useFormStatus 允许子组件访问父表单的状态,类似于上下文提供程序(Context provider)的工作方式。
- 减少 Prop 钻取:通过消除通过多个 props 向下传递表单状态信息的需要,useFormStatus 使组件更简单且更易于管理。
- 关注常见情况:此钩子简化了设计系统中的常见场景,减少了与表单状态交互的组件的样板代码。
语法:
const status = useFormStatus();
const { pending, data, method, action } = useFormStatus();
status
对象具有以下属性:
pending
:布尔值。如果为 true,则表示父级data
:一个实现了 FormData 接口的对象,包含父 正在提交的数据。 如果没有提交动作或没有父 ,则值为 null。method
:字符串值,可以是“get”或“post”。这表示父级 是使用 GET 还是 POST HTTP 方法提交。默认情况下, 将使用 GET 方法,可以通过 method 属性指定。action
:对传递给父 上的 action 属性的函数的引用。如果没有父 ,则该属性为 null。如果为 action 属性提供了 URI 值,或者未指定 action 属性,则 status.action 将为 null。
示例:
import { useFormStatus } from "react-dom";
import action from './actions';
function Submit() {
const status = useFormStatus();
return <button disabled={status.pending}>Submit</button>
}
export default function App() {
return (
<form action={action}>
<Submit />
</form>
);
}
import { useFormStatus } from 'react-dom';
function DesignButton() {
const { pending } = useFormStatus();
return <button type="submit" disabled={pending} />;
}
6. 新的钩子函数: useOptimistic
React 19 引入了 useOptimistic 钩子,以简化异步数据突变期间乐观 UI 更新的处理。这是一种常见模式,当更新数据的请求仍在进行中时,您希望立即向用户显示预期结果(例如,新名称)。
主要功能
- 立即乐观渲染:useOptimistic 允许您定义立即渲染的乐观状态值。这为用户提供了预期结果的即时反馈。
- 自动状态管理:如果更新失败或完成,React 会自动恢复到原始状态。这确保了数据的一致性并避免显示不正确的信息。
- 改善的用户体验:通过提供即时的视觉反馈,useOptimistic 增强了用户体验,使应用程序响应更快、互动性更强。
执行数据突变时的另一种常见 UI 模式是在异步请求进行时乐观地显示最终状态。在 React 19 中,我们添加了一个名为 useOptimistic 的新钩子以使此操作更容易:
function ChangeName({currentName, onUpdateName}) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);
const submitAction = async formData => {
const newName = formData.get("name");
setOptimisticName(newName);
const updatedName = await updateName(newName);
onUpdateName(updatedName);
};
return (
<form action={submitAction}>
<p>Your name is: {optimisticName}</p>
<p>
<label>Change Name:</label>
<input
type="text"
name="name"
disabled={currentName !== optimisticName}
/>
</p>
</form>
);
}
useOptimistic 钩子将在 updateName 请求进行时立即呈现optimisticName。当更新完成或出错时,React 将自动切换回 currentName 值。
有关更多信息,请参阅 useOptimistic 的文档。
https://react.dev/reference/react/useOptimistic
7. 新的钩子函数: useTransition
通过允许在转换(transitions)中使用异步函数,操作简化了状态更新。此自动化功能可管理待处理状态、错误、表单和乐观更新,从而减少手动处理的需要。
在此代码中,useTransition
是一个 React Hook,用于管理转换 - 即可能需要时间的状态更新,例如数据获取或处理,而不会阻塞用户界面。
function UpdateName()
{
const [name, setName] = useState("");
const [error, setError] = useState(null);
const [isPending, startTransition] = useTransition();
const handleSubmit = () => {
startTransition(async () => {
const error = await updateName(name);
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>
);
}
8. 新 API: use
React 19 引入了一个名为 use 的新实验性 API,旨在读取渲染函数中 Promises 或 context 等资源的值。这可以在处理异步数据获取或状态管理时提供更干净、更简洁的代码。
以下是 React 19 中的使用细目
- 目的:此 API 提供了一种在渲染函数中直接访问资源值的机制,无需单独的状态变量或生命周期方法。
- 专注于数据获取:虽然它可以用于上下文等其他资源,但使用主要用于从 Promises 读取值,从而简化数据获取场景。
- 实验性:目前,使用仅在 React 的 Canary 和实验性渠道中可用。它仍在开发中,其行为或用法可能会在未来的稳定版本中发生变化。
需要注意的是,use 有一些限制:
- 范围有限:您只能在组件或钩子内部调用 use。这可确保正确的渲染行为并避免潜在的意外副作用。
- Server Components:在 Server Components 中使用 use 时,最好使用 async 和 await 来获取数据。use 在资源解析后重新渲染组件,而 asyncspan> 和 await 从调用点开始渲染。
例如,你可以使用 use 读取一个 promise,React 将暂停,直到 promise 返回 (resolves ):
import {use} from 'react';
function Page({commentsPromise}) {
// 当 `use` 在 Comments 中挂起, 这个 Suspense 的 Loading 将会显示。
return (
<Suspense fallback={<div>Loading...</div>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
)
}
function Comments({commentsPromise}) {
// `use` 将会挂起直到 promise resolves.
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}
您还可以通过 use
来读取上下文,从而允许您有条件地读取上下文,例如在提前返回之后:
import {use} from 'react';
import ThemeContext from './ThemeContext'
function Heading({children}) {
if (children == null) {
return null;
}
// This would not work with useContext
// because of the early return.
const theme = use(ThemeContext);
return (
<h1 style={{color: theme.color}}>
{children}
</h1>
);
}
use
只能在 render 中调用,与 hooks 类似。与 hooks 不同的是,use
可以有条件地调用。
未来我们计划支持更多使用 use
在 render 中消耗资源的方式。
有关更多信息,请参阅 use 文档。
https://react.dev/reference/react/use
下一篇:React 19新特性和更新介绍 02 - 服务器组件
https://www.cnblogs.com/eddyz/p/18724603
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库