一文搞懂 React 19 新特性

 更新时间:2026年05月29日 08:58:27   作者:阿蓝灬  
React 19 引入多项重要更新,主要聚焦于异步状态管理、性能优化和开发体验提升,这些改进显著减少了状态管理样板代码,提升了应用性能和开发效率,感兴趣的可以了解一下

以下是 React 19 的主要新特性总结及示例说明,基于当前可用信息整理。需要注意的是,React 19 的某些特性在发布时可能有所调整,请务必以最终的官方文档为准。

🔥 React 19 新特性概览

特性类别核心内容主要优势
Actions & 异步处理useActionState, useFormStatus, useOptimistic简化异步状态(pending, error)管理,支持乐观更新
新 Hooksuse() Hook在渲染中直接读取 Promise 或 Context 的值
服务器组件Server Components (稳定版)服务端直接渲染,减小客户端包体积,提升首屏加载和SEO
资源与元数据管理原生 <title>, <meta> 支持;preload, preinit API更好SEO,优化资源加载优先级与性能
开发体验优化Ref 可作为 prop 传递;Context 提供者语法简化减少 forwardRef 使用,减少样板代码
性能优化React Compiler (实验性);自动批处理增强自动优化渲染,减少手动记忆化(如 useMemo)需求

1. Actions 与异步操作管理

Actions 是 React 19 的核心概念,旨在极大地简化表单提交、数据变更等异步操作的处理。

🤔 示例:useActionState处理表单提交

import { useActionState } from 'react';

// 一个模拟的异步 API 调用
async function updateName(formData) {
  const name = formData.get('name');
  if (!name) {
    return 'Name is required';
  }
  // 模拟网络请求
  await new Promise(resolve => setTimeout(resolve, 1000));
  return null; // 表示成功
}

function NameForm() {
  // useActionState 接收一个异步函数和初始状态
  // 返回 [错误状态, 提交动作, 是否进行中]
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const error = await updateName(formData);
      return error;
    },
    null // 初始状态为 null
  );

  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>
        {isPending ? 'Updating...' : 'Update'}
      </button>
      {error && <p style={{color: 'red'}}>{error}</p>}
    </form>
  );
}

说明useActionState 自动管理了提交的 pending 状态和错误状态,你无需手动设置 isLoadingerror 状态变量。

✨ 示例:useOptimistic实现乐观更新

乐观更新是指在服务器确认操作成功之前,就先在 UI 上显示预期的结果,以提升用户体验。

import { useOptimistic, useState } from 'react';

function LikeButton({ initialLikes }) {
  const [likes, setLikes] = useState(initialLikes);
  // useOptimistic 接收当前状态
  // 返回一个乐观状态和一个更新函数
  const [optimisticLikes, setOptimisticLikes] = useOptimistic(
    likes,
    (currentState, amount) => currentState + amount
  );

  const handleClick = async () => {
    // 立即乐观地更新 UI
    setOptimisticLikes(1);
    // 模拟向服务器发送请求
    await likePost(); 
    // 实际更新状态
    setLikes((prev) => prev + 1);
  };

  return (
    <button onClick={handleClick}>
      {optimisticLikes} Likes {/* 按钮上的数字会立即增加 */}
    </button>
  );
}

🔗 示例:useFormStatus在子组件中获取表单状态

在 React 19 中,useFormStatus 是一个专门用于获取表单提交状态信息的 Hook。它旨在简化与表单操作相关的状态管理,尤其适用于需要根据表单提交状态更新UI的场景。

以下是对 useFormStatus 返回的状态对象中各个参数的详细说明。

属性类型描述
pendingBoolean表示其所属的父级 <form> 是否正在提交中。
dataFormData | null包含父级 <form> 正在提交的数据。
methodString表示父级 <form> 提交所使用的 HTTP 方法。
actionFunction | null指向传递给父级 <form> 的 action 属性的函数引用。

深入理解参数

🔄pending

这是最常用的属性。当表单正在提交时(例如,action 函数正在执行),pendingtrue;提交完成后,变为 false

  • 主要用途:提供用户反馈,例如在提交期间禁用提交按钮以防止重复提交,显示加载指示器,或暂时禁用整个表单的输入。

📦data

此属性提供了正在提交的表单数据对象(FormData)。你可以通过 data.get('fieldName') 来访问特定字段的值。这在需要根据提交的数据内容来调整子组件UI时非常有用。如果表单未被提交,其值为 null

🌐method

它反映了表单的 method 属性,通常是 'get''post'。默认情况下,如果未指定 method,其值可能为 'get'。这个信息可以用于在UI上显示更具描述性的状态,例如 “正在创建…” 或 “正在获取…”。

⚡action

此属性提供了对传递给父级 <form>action 属性的那个函数的引用。如果 action 属性不是一个函数(例如一个URL字符串),或者未提供,那么此值为 null

代码示例

下面的例子展示了如何综合使用这些属性,提供一个包含加载状态和提交数据预览的复杂反馈。

import { useFormStatus } from 'react-dom';

// 这是一个位于 <form> 内部的子组件
function AdvancedFormStatus() {
  const { pending, data, method } = useFormStatus();

  return (
    <div style={{ opacity: pending ? 0.7 : 1 }}>
      {/* 显示提交状态 */}
      <button type="submit" disabled={pending}>
        {pending ? (method === 'POST' ? '提交中...' : '获取中...') : '提交'}
      </button>

      {/* 如果正在提交,显示正在提交的数据预览 */}
      {pending && data && (
        <div>
          <p>正在提交的数据:</p>
          <ul>
            {/* 遍历显示所有表单项 */}
            {Array.from(data.entries()).map(([key, value], index) => (
              <li key={index}>{key}: {value.toString()}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

// 在父组件中使用
function MyForm() {
  async function handleSubmit(formData) {
    // 你的表单提交逻辑
    console.log('提交数据:', Object.fromEntries(formData));
    // 模拟网络请求
    await new Promise(resolve => setTimeout(resolve, 2000));
  }

  return (
    <form action={handleSubmit}>
      <input type="text" name="username" placeholder="用户名" />
      <input type="email" name="email" placeholder="邮箱" />
      <AdvancedFormStatus />
    </form>
  );
}

⚠️ 重要使用须知

  1. 组件层级:useFormStatus 必须在其所属的 <form> 元素的子组件内部被调用。它通过React的上下文系统工作,只能访问最近的父表单的状态。将它和表单写在同一个组件层级是无效的。
  2. 依赖 action 属性:它仅能返回使用 action 属性(特别是异步函数)的表单的状态信息。如果你的提交逻辑主要在 onSubmit 事件中处理,并且调用了 e.preventDefault() 阻止了默认行为,那么 action 函数将不会执行,useFormStatus 也就无法正确捕获状态。

希望这份详细的说明能帮助你更好地理解和使用 useFormStatus Hook。
说明:useFormStatus 使得按钮这类子组件可以轻松获取到其所属表单的提交状态,无需通过 props 层层传递。

2.useHook

use Hook 允许你在组件渲染过程中有条件地读取资源(如 Promise 或 Context)的值。

🤔 示例:使用use加载异步数据

import { use, Suspense } from 'react';

// 一个模拟的数据获取函数,返回 Promise
function fetchComments() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(['Great post!', 'Thanks for sharing.']);
    }, 1000);
  });
}

function Comments({ commentsPromise }) {
  // 使用 use Hook 来解析 Promise
  // 需要与 Suspense 配合使用以显示加载状态
  const comments = use(commentsPromise);
  return comments.map((comment, index) => <p key={index}>{comment}</p>);
}

function BlogPost() {
  // 将 Promise 作为 prop 传递给 Comments 组件
  return (
    <div>
      <h1>My Blog Post</h1>
      <Suspense fallback={<div>Loading comments...</div>}>
        <Comments commentsPromise={fetchComments()} />
      </Suspense>
    </div>
  );
}

说明use Hook 为在组件内部处理异步依赖提供了更符合 React 范式的方式,通常需要与 Suspense 结合使用。

3. 服务器组件 (Server Components)

React 19 中,服务器组件已达到稳定状态。服务器组件默认在服务端执行,允许你将数据获取和渲染逻辑放在服务端,仅将渲染出的 HTML 发送到客户端,从而减少客户端的 JavaScript 包大小,提升首屏加载性能。

🤔 示例:服务端组件与客户端组件协同工作

// ProductDetails.server.js - 服务端组件
// 服务端组件可以是异步的,直接访问后端资源
async function ProductDetails({ productId }) {
  // 在服务端直接获取数据
  const product = await db.products.get(productId);

  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      {/* 在服务端组件内部嵌套客户端交互组件 */}
      <AddToCartButton product={product} />
    </div>
  );
}

// AddToCartButton.client.js - 客户端组件
// 使用 "use client" 指令标记
'use client';
import { useOptimistic } from 'react';

function AddToCartButton({ product }) {
  const [cart, setCart] = useOptimistic([]);

  const addToCart = async () => {
    // ... 客户端交互逻辑
  };

  return <button onClick={addToCart}>Add to Cart</button>;
}

说明:通过 'use client' 指令,可以明确划分服务端和客户端组件。服务端组件负责数据和静态内容,客户端组件负责交互,二者可以无缝嵌套。

4. 文档元数据管理

现在,你可以直接在组件内使用 <title>, <meta>, <link> 等标签,React 会自动将它们提升到文档的 <head> 部分。

🤔 示例:在组件中设置页面标题和 Meta 信息

function BlogPost({ post }) {
  return (
    <article>
      {/* 这些标签会被自动提升到 <head> 中 */}
      <title>{post.title}</title>
      <meta name="description" content={post.excerpt} />
      <meta name="keywords" content={post.keywords} />
      <link rel="canonical" href={post.canonicalUrl} />

      {/* 页面内容 */}
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </article>
  );
}

说明:这一特性简化了 SEO 管理,无需再依赖如 react-helmet 等第三方库,并且在服务端渲染 (SSR) 和客户端渲染 (CSR) 下都能正常工作。

5. 资源预加载

新的资源预加载 API(如 preloadpreinit)允许你更精细地控制关键资源(如字体、脚本)的加载时机,优化页面加载性能。

🤔 示例:预加载关键资源

import { preload, preinit } from 'react-dom';

function ProductPage() {
  // 预加载重要字体,避免页面渲染时的字体闪烁
  preload('/fonts/main-font.woff2', { as: 'font', type: 'font/woff2' });
  // 预初始化关键脚本,加快其执行速度
  preinit('/js/critical-checkout.js', { as: 'script' });

  return (
    <div>
      {/* 页面内容 */}
    </div>
  );
}

6. 开发体验优化

Ref 作为 Prop 传递

函数组件现在可以直接接受 ref 作为 prop,无需使用 forwardRef 进行包裹。

// React 19 之前:需要 forwardRef
const MyInput = React.forwardRef((props, ref) => {
  return <input {...props} ref={ref} />;
});

// React 19:直接作为 prop 使用
function MyInput({ ref, ...props }) {
  return <input {...props} ref={ref} />;
}

function App() {
  const inputRef = useRef(null);
  return <MyInput ref={inputRef} />;
}

Context 提供者语法简化

// 之前
<ThemeContext.Provider value="dark">
  <Children />
</ThemeContext.Provider>

// React 19 简化语法
<ThemeContext value="dark">
  <Children />
</ThemeContext>

7. 性能优化:React Compiler (实验性)

React 19 引入了实验性的 React Compiler。它能够在构建时自动优化你的组件,例如自动进行记忆化(类似于 useMemo, useCallback),从而减少不必要的重新渲染,可能带来显著的性能提升。

// 开发者编写的代码
function MyComponent({ data }) {
  const transformedData = expensiveTransformation(data);
  return <div>{transformedData}</div>;
}

// React Compiler 可能会在背后自动优化,类似于:
function MyComponent_optimized({ data }) {
  const transformedData = useMemo(() => expensiveTransformation(data), [data]);
  return <div>{transformedData}</div>;
}

注意:此功能目前仍是实验性的,可能需要手动启用。

到此这篇关于一文搞懂 React 19 新特性的文章就介绍到这了,更多相关React 19 新特性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • webpack4+react多页面架构的实现

    webpack4+react多页面架构的实现

    webpack在单页面打包上应用广泛,以create-react-app为首的脚手架众多。这篇文章主要介绍了webpack4+react多页面架构的实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • Vite+React搭建开发构建环境实践记录

    Vite+React搭建开发构建环境实践记录

    这篇文章主要介绍了Vite+React搭建开发构建环境实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • react页面中存在多个input时巧妙设置value属性方式

    react页面中存在多个input时巧妙设置value属性方式

    这篇文章主要介绍了react页面中存在多个input时巧妙设置value属性方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • react如何使用mobx6动态加载数据

    react如何使用mobx6动态加载数据

    MobX是一个强大而简单的状态管理工具,它可以帮助我们更好地组织和管理React应用程序中的数据流,本文给大家介绍react如何使用mobx6动态加载数据,感兴趣的朋友跟随小编一起看看吧
    2024-02-02
  • React 18版本配置rem 和 vw的详细步骤

    React 18版本配置rem 和 vw的详细步骤

    这篇文章主要介绍了React 18版本配置rem 和 vw的详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • React中条件渲染的常见方法总结

    React中条件渲染的常见方法总结

    条件渲染在React开发中非常重要的功能,它允许开发人员根据条件控制渲染的内容,在创建动态和交互式用户界面方面发挥着至关重要的作用,本文总结了常用的的条件渲染方法,需要的朋友可以参考下
    2024-01-01
  • React封装全屏弹框的方法

    React封装全屏弹框的方法

    这篇文章主要为大家详细介绍了React封装全屏弹框的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 如何在React中直接使用Redux

    如何在React中直接使用Redux

    这篇文章主要介绍了如何在React中直接使用Redux,目前redux在react中使用是最多的,所以我们需要将之前编写的redux代码,融入到react当中去,本文给大家详细讲解,需要的朋友可以参考下
    2022-11-11
  • react学习每天一个hooks useWhyDidYouUpdate

    react学习每天一个hooks useWhyDidYouUpdate

    这篇文章主要为大家介绍了react学习每天一个hooks useWhyDidYouUpdate使用示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 浅谈React中组件间抽象

    浅谈React中组件间抽象

    这篇文章主要介绍了浅谈React中组件间抽象,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01

最新评论