•  阅读 3 分钟

React 19 更新精简纪要

最近知名的 React 开发者 Kent C. Dodds 发表 React 19 的功能更新纪要,精简到一页 PDF。现在我以列表的形式翻译一份:

React Server Components(React 服务器组件)

服务器渲染的组件可以在构建时或根据请求执行。

// dashboard.tsx
import * as db from './db.ts'
import { createOrg } from './org-actions.ts'
import { OrgPicker } from './org-picker.tsx'

// look! it' async
export async function Dashboard() {
  // look! await!
  const orgs = await db.getOrgs()

  { /* 这是仅在服务端运行的代码 */ }
  return (
    <div>
      <h1>Dashboard</h1>
      {/* OrgPicker 是一个客户端组件 */}
      <OrgPicker orgs={orgs} onCreateOrg={createOrg} />
    </div>
  )
}

Actions

异步函数可以自动处理表单提交、错误状态和自动优化更新。

<form action={createOrg} />

useActionState

管理表单状态,在 JavaScript 不可操作时提供等待体验。

const [error, submitAction, isPending] = useActionState(async () => { /* ... */ }, null)

useFormStatus

无需通过逐层传递属性即可访问父表单的状态。

const { pending, data, method, action } = useFormStatus()

useOptimistic

在异步请求进行时显示乐观状态,useOptimistic

const [optimisticName, setOptimisticname] = useOptimistic(name)

支持异步脚本

在组件树中的任意位置渲染异步脚本,并自动去重。

<script async src="https://tie.pub/script.js" />

改进的第三方脚本兼容性

在页面水合过程中,<head><body>中的意外标签会被跳过,避免不匹配错误。

'use client'

标记可以被服务器组件引用并使用客户端 React 功能的代码。

// org-picker.tsx
'use client'

export function OrgPicker({ orgs, onCreateOrg }) {
  // orgs, onCreateOrg 属性值可以来自服务端组件
  // 这个组件可以使用 useState, useActionState, useEffect,
  // useRef 等等

  return <div />
}

'use server'

标记可以从客户端代码调用的服务器端函数。

// org-actions.ts
'use server'

// 这个函数可以在客户端调用
export async function createOrg(prevResult, formData) {
  // 与 db 一起创建 org
  // 返回最终结果
}

支持文档元数据

自动把 <title>, <meta><link> 标签提升至 <head>

<title>My Blog</title>
<meta name="author" content="Kent" />

样式支持 precedence 属性

支持在并发渲染环境中按优先顺序插入样式表。

<link rel="stylesheet" href="foo.css" precedence="default" />

{ /* 下面的设置在文档中有更高优先级 */ }
<link rel="stylesheet" href="bar.css" precedence="high" />

资源预加载 APIs

预加载字体,脚本和样式等资源来优化性能。

preload('https://example.com/font.woff', { as: 'font' })
preconnect('https://example.com')

支持自定义标签元素

React 现在全面支持自定义标签元素,并且一致地处理属性(properties)和特性(attributes)。

<custom-element prop1="value" />

更好的错误报告

自动去重错误,并为根组件引入 onCaughtErroronUncaughtError 处理程序。

createRoot(container, {
  onCaughtError(error, errorInfo) {
    console.error('Caught error', error, errorInfo.componentStack)
  },
  onUncaughtError(error, errorInfo) {
    console.error('Uncaught error', error, errorInfo.componentStack)
  },
})

use

在渲染期间读取资源,例如 promise 或上下文,从而实现条件使用。

const comments = use(commentsPromise)
const theme = use(ThemeContext)

ref 回调清理

ref 回调现在可以返回一个清理函数。

<input ref={ref => console.log('cleanup')} />

流线型上下文 API

使用 <Context> 直接替换 <Context.Provider>

<LanguageContext value="pl-PL">{children}</LanguageContext>

useDeferredValue 初始值

useDeferredValue hook 现在支持初始值。

const deferredValue = useDeferredValue(value, 'initial')

Hydration Error Diffs(水合错误差异)显示

改进了水合错误的错误日志记录,当发生不匹配时提供详细的差异信息。

Uncaught Error: Hydtation failed
  <App>
    <span>
+    Client
-    Server

ref 作为属性

在函数组件中直接作为 props 传递 refs

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