React 19 新特性
约 766 字大约 3 分钟
布欧-Lewyon
2026-05-15
React 19 在 18 的基础上进一步简化了开发体验,引入 Actions、use() Hook、改进的 ref 和 Context 等。
Actions
React 19 原生支持异步表单处理。
function UpdateName() {
const [name, setName] = useState('')
const [error, setError] = useState<Error | null>(null)
const [isPending, startTransition] = useTransition()
const submitAction = async (formData: FormData) => {
const newName = formData.get('name') as string
startTransition(async () => {
const result = await updateName(newName)
if (result.error) {
setError(result.error)
} else {
setName(newName)
}
})
}
return (
<form action={submitAction}>
<input type="text" name="name" defaultValue={name} />
<button type="submit" disabled={isPending}>
{isPending ? 'Updating...' : 'Update'}
</button>
{error && <p>{error.message}</p>}
</form>
)
}useActionState
import { useActionState } from 'react'
// useActionState 将 pending / formData / error 封装在一起
function UpdateNameForm() {
const [state, submitAction, isPending] = useActionState(
async (previousState: State, formData: FormData) => {
const error = await updateName(formData.get('name') as string)
if (error) return { error }
return { success: true }
},
{ error: null, success: false }
)
return (
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>
{isPending ? 'Saving...' : 'Submit'}
</button>
{state.error && <p>{state.error.message}</p>}
</form>
)
}use() Hook
use() 可以在条件/循环中直接读取 Promise 或 Context。
import { use } from 'react'
// 读取 Promise(在 Suspense 下自动处理 pending/error)
function Comments({ commentsPromise }: { commentsPromise: Promise<Comment[]> }) {
const comments = use(commentsPromise) // 不需要 useEffect + useState
// 父组件用 <Suspense> 包裹
return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>
}
// 读取 Context(可在条件中调用)
function ThemeButton() {
// ✅ React 19:可在条件、循环中调用
if (typeof window === 'undefined') {
return <DefaultButton />
}
const theme = use(ThemeContext)
return <button className={`btn-${theme}`} />
}ref as Prop
React 19 中 ref 可作为普通 prop 传递,不再需要 forwardRef。
// React 18 及之前
const FancyInput = forwardRef<HTMLInputElement, Props>(
(props, ref) => <input ref={ref} {...props} />
)
// React 19 —— ref 是普通 prop
function FancyInput({ ref, ...props }: Props & { ref?: React.Ref<HTMLInputElement> }) {
return <input ref={ref} {...props} />
}Context as Provider
// React 18
<ThemeContext.Provider value={theme}>
{children}
</ThemeContext.Provider>
// React 19 —— Context 本身可作为 Provider
<ThemeContext value={theme}>
{children}
</ThemeContext>Server Components
// Server Component —— 只在服务器运行,不发送到客户端
// async 组件、直接访问数据库、文件系统
// app/UserList.server.tsx
import db from '@/db'
export default async function UserList() {
// ✅ 直接查询数据库(不会暴露给客户端)
const users = await db.query('SELECT * FROM users LIMIT 10')
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)
}useOptimistic
import { useOptimistic, useActionState } from 'react'
function LikeButton({ likes }: { likes: number }) {
const [optimisticLikes, addOptimistic] = useOptimistic(
likes,
(state, amount: number) => state + amount // 乐观更新函数
)
const handleLike = async () => {
addOptimistic(1) // 立即 +1(乐观)
await api.addLike() // 实际请求
// 请求成功后 React 自动用真实数据覆盖乐观值
}
return (
<button onClick={handleLike}>
❤️ {optimisticLikes}
</button>
)
}升级清单
1. forwardRef → ref 直接作为 prop
2. Context.Provider → Context 直接作为 Provider
3. use() 替代 useEffect + fetch + useState(简单场景)
4. useActionState 替代手动 useTransition + useState
5. useOptimistic 实现乐观更新(替代 React Query 乐观更新)
6. Server Components 仅在 RSC 框架中使用(Next.js)升级行为变更
1. Strict Mode 可以只包裹部分组件
2. 废弃的 API 已移除(propTypes、defaultProps 部分)
3. 不再需要 `import React from 'react'`(React 17+ 已支持)
4. act 警告更精准小结
- Actions:
useActionState+<form action={fn}>简化表单。 - use():在条件/循环中读 Promise 和 Context。
- ref as prop:不再需要
forwardRef。 - Context as Provider:更简洁。
- Server Components:服务端直接渲染 UI,减少客户端 JS。
- useOptimistic:原生支持乐观更新。
上一节:React 18 并发模式 下一节:无(完结)
