当前位置: 首页 > article >正文

React 19 新特性总结

具体详见官网:
中文:React 19 新特性
英文:React 19 新特性

核心新特性

1. Actions

解决问题:简化数据变更和状态更新流程

  • 以前需要手动处理待定状态、错误、乐观更新和顺序请求
  • 需要维护多个状态变量(isPending, error 等)

新特性

function UpdateName() {
  const [state, submitAction, isPending] = useActionState(
    async (prevState, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) return error;
      redirect("/path");
      return null;
    },
    null
  );

  return (
    <form action={submitAction}>
      <input name="name" />
      <button disabled={isPending}>Update</button>
      {state?.error && <p>{state.error}</p>}
    </form>
  );
}

主要改进

  • 自动处理待定状态
  • 内置错误处理
  • 支持乐观更新
  • 简化表单处理

2. useFormStatus

解决问题:简化表单组件状态访问

  • 避免通过 props 传递表单状态
  • 提供统一的表单状态访问方式
function SubmitButton() {
  const { pending, data, method } = useFormStatus();
  return (
    <button disabled={pending}>
      {pending ? 'Submitting...' : 'Submit'}
    </button>
  );
}

3. useOptimistic

解决问题:提供更好的用户体验

  • 立即显示操作结果
  • 处理异步操作的状态更新
function LikeButton({ id }) {
  const [likes, setLikes] = useState(0);
  const [optimisticLikes, addOptimisticLike] = useOptimistic(
    likes,
    (state, increment) => state + increment
  );

  async function handleLike() {
    addOptimisticLike(1); // 立即更新 UI
    await updateLikes(id); // 后台进行实际更新
  }
}

4. use() Hook

解决问题:统一资源使用方式

  • 简化 Promise 和 Context 的使用
  • 支持条件性使用
  • 提供更好的类型推断
function Comments({ commentsPromise }) {
  const comments = use(commentsPromise); // 自动处理 Suspense
  return comments.map(comment => <p>{comment}</p>);
}

架构改进

1. Document 流式渲染

解决问题:改善首次加载体验

  • 支持 HTML 流式传输
  • 优化资源加载顺序
function AsyncPage() {
  return (
    <Document>
      <Suspense fallback={<Loading />}>
        <AsyncContent />
      </Suspense>
    </Document>
  );
}

2. 资源处理优化

样式表支持

解决问题:简化样式管理

  • 自动处理样式表加载顺序
  • 支持组件级样式声明
function Component() {
  return (
    <>
      <link rel="stylesheet" href="styles.css" precedence="default" />
      <div className="styled-content">...</div>
    </>
  );
}
异步脚本支持

解决问题:优化脚本加载

  • 自动处理脚本去重
  • 优化加载优先级
function MyComponent() {
  return (
    <div>
      <script async={true} src="widget.js" />
      <div>Widget Content</div>
    </div>
  );
}

开发体验改进

1. 错误处理增强

解决问题:提供更清晰的错误信息

  • 消除重复错误日志
  • 提供更详细的错误上下文
createRoot(container, {
  onCaughtError: (error) => {
    // 错误边界捕获的错误
  },
  onUncaughtError: (error) => {
    // 未被捕获的错误
  },
  onRecoverableError: (error) => {
    // 可恢复的错误
  }
});

2. 自定义元素支持

解决问题:改善与 Web Components 的集成

  • 完整支持自定义元素
  • 正确处理属性和属性传递

最佳实践建议

  1. 渐进式采用

    • 优先使用新的表单处理方式
    • 在关键交互中使用乐观更新
    • 利用新的资源加载优化
  2. 性能优化

    • 使用流式渲染改善加载体验
    • 合理使用资源预加载
    • 优化并发更新
  3. 错误处理

    • 使用新的错误边界
    • 实现适当的降级策略
    • 监控错误模式

服务器组件

1. 服务器组件基础

解决问题:优化应用性能和开发体验

  • 减少客户端 bundle 大小
  • 直接访问后端资源
  • 改善数据获取模式
// 服务器组件
async function Notes() {
  // 直接访问数据库,无需 API 层
  const notes = await db.notes.getAll();
  
  return (
    <div>
      {notes.map(note => (
        <Expandable key={note.id}>
          <p>{note.content}</p>
        </Expandable>
      ))}
    </div>
  );
}

2. 服务器组件与客户端组件集成

解决问题:平滑处理服务器和客户端组件交互

  • 支持渐进式增强
  • 保持交互性
  • 优化数据流
// 服务器组件
import Expandable from './Expandable';  // 客户端组件

async function NotesContainer() {
  const notes = await db.notes.getAll();
  
  return (
    <div>
      {/* 服务器组件可以渲染客户端组件 */}
      <Expandable>
        <NotesList notes={notes} />
      </Expandable>
    </div>
  );
}

// 客户端组件
'use client'
function Expandable({ children }) {
  const [expanded, setExpanded] = useState(false);
  
  return (
    <div>
      <button onClick={() => setExpanded(!expanded)}>
        {expanded ? 'Collapse' : 'Expand'}
      </button>
      {expanded && children}
    </div>
  );
}

3. 异步组件

解决问题:简化异步数据处理

  • 支持 async/await 语法
  • 自动处理 Suspense 集成
  • 优化加载状态
// 服务器组件中的异步数据获取
async function Page({ id }) {
  const note = await db.notes.get(id);
  // 开始获取评论但不等待
  const commentsPromise = db.comments.get(id);
  
  return (
    <div>
      <h1>{note.title}</h1>
      <Suspense fallback={<Loading />}>
        <Comments commentsPromise={commentsPromise} />
      </Suspense>
    </div>
  );
}

Refs 作为 Props

1. 将 ref 作为 prop

从 React 19 开始,你现在可以在函数组件中将 ref 作为 prop 进行访问:

function MyInput({placeholder, ref}) {
  return <input placeholder={placeholder} ref={ref} />
}

//...
<MyInput ref={ref} />

新的函数组件将不再需要 forwardRef,我们将发布一个 codemod 来自动更新你的组件以使用新的 ref prop。在未来的版本中,我们将弃用并移除 forwardRef。

2. Ref 稳定性改进

解决问题:优化 ref 更新和同步

  • 更可预测的 ref 更新时机
  • 更好的并发模式支持
  • 改进的性能特性
function AutoFocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  
  // ref 回调模式的改进
  const setRef = useCallback((element: HTMLInputElement | null) => {
    if (element) {
      element.focus();
    }
  }, []);
  
  return <input ref={setRef} />;
}

服务器组件最佳实践

  1. 数据获取策略

    • 在服务器组件中直接访问数据源
    • 使用流式传输处理大量数据
    • 实现适当的缓存策略
  2. 组件分割

    • 将有状态逻辑的组件标记为客户端组件
    • 保持服务器组件纯粹
    • 优化组件边界
  3. 性能优化

    • 使用服务器组件减少客户端 bundle
    • 实现渐进式加载
    • 优化数据预取
// 示例:优化的服务器组件结构
async function BlogPost({ id }) {
  const post = await db.posts.get(id);
  const authorPromise = db.authors.get(post.authorId);
  const commentsPromise = db.comments.get(id);
  
  return (
    <article>
      <h1>{post.title}</h1>
      <Suspense fallback={<AuthorSkeleton />}>
        <Author authorPromise={authorPromise} />
      </Suspense>
      <Content>{post.content}</Content>
      <Suspense fallback={<CommentsSkeleton />}>
        <Comments commentsPromise={commentsPromise} />
      </Suspense>
    </article>
  );
}

注意事项

  1. 服务器组件限制

    • 不能使用浏览器 API
    • 不能使用状态和生命周期
    • 需要正确处理数据获取错误
  2. Ref 使用考虑

    • 注意 ref 的生命周期
    • 合理处理 ref 清理
    • 避免过度依赖 ref
  3. 性能注意事项

    • 平衡服务器和客户端渲染
    • 合理使用 Suspense 边界
    • 优化数据预加载策略

http://www.kler.cn/a/516945.html

相关文章:

  • 09_异步加载_单例模式_常量类配置_不可销毁
  • C# volatile 使用详解
  • 腾讯 Hunyuan3D-2: 高分辨率3D 资产生成
  • Moretl FileSync增量文件采集工具
  • Redis使用基础
  • Linux 执行 fdisk -l 出现 GPT PMBR 大小不符 解决方法
  • Chrome 132 版本新特性
  • tomcat shutdown.sh不能关闭tomcat 进程
  • K8S-标签管理,探针,名称空间,rc控制器,svc服务发现
  • 聚类问题(K-means,系统聚类,SBSCAN算法)
  • 构建沉浸式汉语学习环境
  • Neural networks 神经网络
  • 2025春招 SpringCloud 面试题汇总
  • AI Agent:深度解析与未来展望
  • Spring自定义BeanPostProcessor实现bean的代理Java动态代理知识
  • 【JVM】OOM
  • python——Django 框架
  • QT QListWidget控件 全面详解
  • 使用LabVIEW的History功能实现队列数据的读取而不清空
  • 在 VS Code 中使用 TypeScript 进行开发和打包的几种方法
  • Vue.js 渐进式增强:如何逐步为传统项目注入活力
  • 【深度学习】微积分
  • 移动端ui库uv-ui实现弹窗式picker选择控件
  • Node.js NativeAddon 构建工具:node-gyp 安装与配置完全指南
  • 【小游戏篇】三子棋游戏
  • Ubuntu18.04 搭建DHCP服务器