React 19.3 新特性总结

2026-09-15
2244 字约 8 分钟
...

React 19.3 已发布到 npm,核心是把去年以实验 API 形式公布的 View Transitions 和 Fragment Refs 正式转正,同时新增了几个 DOM 与 RSC 相关的 API。下面按特性整理。

一、View Transitions(视图过渡动画,正式发布)

是什么

<ViewTransition> 是基于浏览器原生 View Transition API 封装的组件。把你想要加动画的元素包起来,当元素进入、退出、移动或尺寸变化时,React 自动播放过渡动画。

基本用法

import { ViewTransition } from 'react';

{isShowing && (
  <ViewTransition>
    <Component />
  </ViewTransition>
)}

只要组件树发生变化(被挂载、卸载或样式改变),并且这次更新被标记为 Transition(即通过 startTransition、<Suspense> 揭示或 useDeferredValue 触发),就会播放动画。紧急更新不会触发动画,这是设计上的选择 —— 紧急更新要立刻反映到 UI 上。

四种动画类型

React 根据组件树变化方式自动决定播哪种:

  • enter: <ViewTransition> 被添加 → 入场动画
  • exit: <ViewTransition> 被移除 → 离场动画
  • update: 子元素样式或内容变了 → 更新动画
  • share: 同名的 <ViewTransition> 在 A 处被移除、在 B 处被添加 → 跨位置共享动画

默认是平滑的交叉淡入淡出。要自定义动画,可以传 View Transition Class(CSS 里定义 ::view-transition-group(.xxx) 之类的选择器),或者用 Web Animations API 的事件钩子 onEnter / onExit / onShare / onUpdate。

目前 <ViewTransition> 仅在 Web 端可用,原生移动端(React Native)还在跟进。

用 addTransitionType 区分"同一种更新的不同方向"

同一个状态变更可能有多种动画需求。典型场景:轮播图,前进到第 3 页要右进左出、后退到第 3 页要左进右出 —— 两次操作都是 setCurrentSlide(3),但动画方向相反。

解法:在 startTransition 里调用 addTransitionType 标记本次更新的"原因类型",然后在 JSX 上按类型配动画:

function nextSlide() {
  startTransition(() => {
    addTransitionType('next');
    setCurrentSlide(c => c + 1);
  });
}

function previousSlide() {
  startTransition(() => {
    addTransitionType('previous');
    setCurrentSlide(c => c - 1);
  });
}
<ViewTransition
  enter={{
    'next': 'from-right',
    'previous': 'from-left',
  }}
  exit={{
    'next': 'to-left',
    'previous': 'to-right',
  }}
>
  <Page />
</ViewTransition>

Transition Type 也会作为浏览器 view-transition-type 加到元素上,方便在 CSS 里用 :active-view-transition-type(...) 限定作用域。

和 Suspense 结合:给 fallback、image、字体加动画

把 <Suspense> 边界也包进 <ViewTransition>,fallback 揭示时会有从占位过渡到真实内容的更新动画:

<ViewTransition>
  <Suspense fallback={<Loading />}>
    <Component />
  </Suspense>
</ViewTransition>

进阶用法 —— 用 update 和 default 区分初次揭示与后续切换:

<ViewTransition update="auto" default="none">
  <Suspense fallback={<Fallback />}>
    <img src={imageSrc} />
  </Suspense>
</ViewTransition>

default 控制首次加载行为(默认会动画),update 控制后续切换行为。cached 的图片没必要每次都动画 —— 用 default="none" 跳过首次。

Suspense 动画的几个 UX 原则:

  • fallback 出现时不动画(要立即可见,否则用户以为卡住)
  • fallback 切到真实内容时动画
  • 没有挂起的子元素直接显示,不要动画

二、Fragment Refs(正式发布)

解决的痛点

需要操作组件渲染的 DOM 节点时(绑事件、监听可见性、移动焦点),通常用 ref。但有两种情况用 ref 很难受:

  1. 组件渲染的是一组没有单一父元素的兄弟节点(Fragment 形式)
  2. 组件不把 ref 转发到内部元素,比如第三方库的组件

传统解法是套一层 <div> 持有 ref —— 但会污染布局结构,而且对不暴露 ref 转发机制的库无效。

解法:把 ref 直接传给 <Fragment>

import { Fragment, useRef, useEffect } from 'react';

function Component() {
  const fragmentRef = useRef(null);

  useEffect(() => {
    const fragmentInstance = fragmentRef.current;
    fragmentInstance.focus();
  }, []);

  return (
    <Fragment ref={fragmentRef}>
      {posts.map(post => (
        <Heading key={post.id}>{post.title}</Heading>
      ))}
    </Fragment>
  );
}

ref.current 现在是 FragmentInstance 对象,暴露一组常用的 DOM 方法:

  • addEventListener / removeEventListener / dispatchEvent —— 给第一层子元素批量绑事件
  • focus / focusLast —— 焦点控制
  • measure —— 测量布局
  • 等等

FragmentInstance 操作的是"作为一组的子元素",不改变 DOM 结构,所以不会破坏现有样式和布局。

想自动包一层 ref 又不想污染结构,Fragment Refs 是首选。

三、react-dom 新增 browser

react-dom 导出新的 browser API,让 SSR 框架能拿到渲染层的全局 loader 数据(请求级缓存、cookie、请求头等)。这是 loaderData 类型的钩子。

import { use } from 'react';
import { browser } from 'react-dom';

function useBrowserQuery(query, options) {
  if (options.initialData === undefined) {
    use(browser());
  }
  return useQuery(query, options);
}

function ProductDetails({ productId, initialData }) {
  const product = useBrowserQuery(
    `/api/products/${productId}`,
    { initialData }
  );
  // ...
}

use(browser()) 的作用是告诉 React:“这里依赖渲染层的全局数据,请按请求级缓存处理”,避免跨请求的数据泄漏。具体协议由框架实现(Remix、Next.js 等)。

四、Trusted Types 支持

React DOM 现在支持 Trusted Types —— 浏览器层面的 XSS 防护机制。在启用 Trusted Types 的页面里,React 不再用字符串构造 DOM,而是通过 Trusted Types 策略创建,避免被 CSP 拦下。

应用开发者无需改动代码,升级到 19.3 自动生效。如果你的应用被 TrustedHTML 之类报错,升级即可。

五、<Context> 可在 Server Component 直接渲染

之前 Server Component 不能渲染 <Context.Provider> —— Provider 是客户端组件标记,服务端没法用。新版允许:

// user-context.js —— 客户端模块
'use client';
import { createContext } from 'react';
export const UserContext = createContext(null);

// server-component.js
import { UserContext } from './user-context';

export function UserProvider({ user, children }) {
  return (
    <UserContext value={user}>
      {children}
    </UserContext>
  );
}

关键点:

  • Provider 仍要 'use client'(因为 Context 本身需要客户端能力)
  • 但 Provider 组件本身可以在 Server Component 里被调用,把 user 数据传给一整棵客户端子树
  • Server Component 端不再需要写一个包装层把 Provider 挪到 Client Component 里

特别适合"只在 server 端构造一次数据、整个客户端树共享"的场景(比如用户信息、主题、地区设置等只读 Context)。

六、Changelog

完整更新列表与重要变更见官方仓库 CHANGELOG.md。其他比较重要的修复:

  • react: 把多个 Transition 渲染解耦,慢的 Transition 不再阻塞其他不相关的 Transition [#37290]
  • react-dom: 严格模式在注水阶段双调用副作用,与客户端渲染根节点行为对齐 [#35961]
  • react: use 在条件分支里被错误调用时会给出警告 [#37104]

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
react2025-12-02
useEffect与useLayoutEffect对比
在 React Hooks 中, 和 都用于处理副作用逻辑,例如订阅、事件监听、DOM 操作等。但它们有着本质性的执行时机差异,这影响到页面渲染、布局抖动、性能表现等关键点。 1\. 执行时机的核心区别 在 React 的渲染流程中: 1. 渲染(Render phase) React 根据 state/props 计算 UI,生成虚拟 DOM,不访问真实 DOM。 2. 提交(Commit phase) React 将虚拟 DOM 变...
学习
react2025-08-03
在 React 中实现倒计时功能会有什么坑
倒计时 倒计时是一个非常常见的业务场景,但是在 React 中实现起来,却不算简单。 首先我们来看这段倒计时代码,它能否正常执行? 来看看实际表现效果 可以看到计时器在不断执行,但是 的值却没有变。 这是一个很经典的问题:React 闭包陷阱 。 我们来详细分析下: 的依赖数组 是空的,这意味着 effect 只会在组件挂载时执行一次,而不会在 状态更新时重新执行。所以 回调函数中捕获的 值始终是初始值 。 这个问题解决起来也很简单,有...
学习面试
react2025-07-30
React性能优化三剑客:memo、useMemo和useCallback详解
前言 在React开发中,性能优化是一个永恒的话题。今天我们就来深入探讨React提供的三个重要性能优化工具: 、 和 ,它们如何帮助我们构建更高效的React应用。 1\. 为什么需要性能优化? 🤔 React的核心机制是当组件的state或props发生变化时,组件会重新渲染。但有时这种重新渲染是不必要的: 父组件更新导致所有子组件重新渲染 ,即使子组件的props没有变化 复杂计算在每次渲染时重复执行 ,消耗大量资源 函数引用在...
学习面试
react2025-06-05
React 中 useDeferredValue 和 startTransition 的核心区别与使用场景
React 中 和 ,两者都用于优化性能,但适用场景和实现方式不同。 核心概念解析 1\. useDeferredValue:延迟值更新 作用 :告诉 React 延迟更新某个值 ,直到所有高优先级渲染任务完成。 适用场景 :当某个值的更新会触发计算密集型渲染(如复杂列表、图表),但需要优先保证其他高优先级 UI(如输入框)的响应。 机制 : 保持旧值显示,后台计算新值。 计算完成后,用新值更新 UI,期间允许用户继续交互。 示例 :...
学习
react2024-12-18
Antd 样式覆盖
&nbsp; 目前作者所在的业务正在升级 Antd5.0,不得不说 Antd5.0 真的太香了,但是由于团队的 UE 规范进行了大改版,Antd5.0 所有的 必须对齐最新的规范,因此就需要对 Antd5.0 组件做主题定制。 现状 目前针对项目中使用的 antd 高频组件进行了梳理,并且根据规范基于 design token 对这些高频组件进行样式定制,对于主题色、圆角、边框、字体等用户 高的主题都已经满足团队规范。 虽然 Desig...
学习
react2024-12-06
React 19 终于发布,一大波新功能正式升级
这篇文章主要介绍了 React 19 的新功能,包括 Actions 自动处理数据突变相关状态,新增的 useActionState、useFormStatus、useOptimistic 等 hook,新的 use API 读取渲染资源,新的 React DOM 静态 API 生成静态站点,以及 React 服务器组件中的 RSC 和 RSA 等内容。同时提到后续会分享针对旧版功能的优化和改良。 关联问题: React 19 性能如何...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录