React 19 带来了多年来最重要的更新,包括 Server Components、Actions、新的 Hook 以及完全重写的渲染引擎。本文将全面解析这些新特性,帮助你快速掌握 React 19 的强大功能。
React 19 概览
React 19 是一个重要的里程碑版本,引入了许多期待已久的功能:
- React Compiler:自动优化组件性能
- Server Components:在服务器上渲染组件
- Actions:简化表单和异步操作
- 新的 Hook:useOptimistic、useActionState 等
- 改进的 Suspense:更好的加载状态处理
升级要求
{
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0"
}
}
Server Components
Server Components (RSC) 是 React 19 最重磅的功能,它允许组件在服务器上渲染,只将必要的 HTML 发送到客户端。
基本用法
// app/page.js (Server Component)
async function BlogPage() {
const posts = await db.posts.findMany()
return (
<div>
<h1>Blog</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
))}
</div>
)
}
Server vs Client Components
| 特性 | Server Components | Client Components |
|---|---|---|
| 运行位置 | 服务器 | 浏览器 |
| 可以访问后端 | ✅ | ❌ |
| 可以交互 | ❌ | ✅ |
| 增加包大小 | ❌ | ✅ |
标记 Client Component
// ✅ Client Component - 可以有状态和交互
'use client'
import { useState } from 'react'
export function LikeButton() {
const [liked, setLiked] = useState(false)
return (
<button onClick={() => setLiked(!liked)}>
{liked ? '❤️' : '🤍'}
</button>
)
}
混用 Server 和 Client Components
// Server Component
import { LikeButton } from './like-button'
async function Post({ id }) {
const post = await db.post.findUnique({ where: { id } })
return (
<article>
<h2>{post.title}</h2>
<p>{post.content}</p>
<!-- Client Component 仍然可以嵌套 -->
<LikeButton postId={post.id} />
</article>
)
}
Actions 与表单处理
React 19 引入了 Actions 的概念,简化了表单提交和异步操作的处理。
基本用法
// 定义 Action
async function updateName(formData) {
const name = formData.get('name')
await db.user.update({ name })
}
// 在表单中使用
function NameForm() {
return (
<form action={updateName}>
<input type="text" name="name" />
<button type="submit">Update</button>
</form>
)
}
useActionState Hook
import { useActionState } from 'react'
function ChangeNameForm() {
const [state, formAction, isPending] = useActionState(
async (prevState, formData) => {
const name = formData.get('name')
await updateName(name)
return { success: true, error: null }
},
{ success: false, error: null }
)
return (
<form action={formAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>
{isPending ? 'Updating...' : 'Update'}
</button>
{state.success && <p>Name updated!</p>}
</form>
)
}
useFormStatus Hook
import { useFormStatus } from 'react'
function SubmitButton() {
const { pending } = useFormStatus()
return (
<button type="submit" disabled={pending}>
{pending ? 'Submitting...' : 'Submit'}
</button>
)
}
function Form() {
async function submit(formData) {
// 提交逻辑
}
return (
<form action={submit}>
<SubmitButton />
</form>
)
}
useOptimistic Hook
用于在等待服务器响应时立即更新 UI,提供更流畅的用户体验。
import { useOptimistic } from 'react'
function LikeButton({ postId, initialLiked }) {
const [liked, setLiked] = useState(initialLiked)
const optimisticLiked = useOptimistic(liked, {
pending: true,
action: async (current) => {
// 乐观更新:立即切换状态
const newValue = !current
// 后台执行服务器更新
await toggleLike(postId, newValue)
return newValue
}
})
return (
<button
onClick={() => optimisticLiked.action(optimisticLiked.value)}
disabled={optimisticLiked.pending}
>
{optimisticLiked.value ? '❤️' : '🤍'}
{optimisticLiked.pending && ' (updating...)'}
</button>
)
}
实际应用示例
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Learn React 19', done: false }
])
const [optimisticTodos, addOptimistic] = useOptimistic(
todos,
(state, newTodo) => [...state, { ...newTodo, pending: true }]
)
async function addTodo(formData) {
const text = formData.get('text')
const newTodo = { id: Date.now(), text, done: false }
// 立即显示
addOptimistic(newTodo)
// 服务器更新
await db.todos.create({ data: newTodo })
// 更新真实状态
setTodos(prev => [...prev, newTodo])
}
return (
<form action={addTodo}>
<input type="text" name="text" />
<button type="submit">Add</button>
<ul>
{optimisticTodos.map(todo => (
<li key={todo.id}>
{todo.text}
{todo.pending && ' (saving...)'}
</li>
))}
</ul>
</form>
)
}
增强的 useTransition
React 19 改进了 useTransition,使其更强大且易于使用。
import { useTransition } from 'react'
function SearchResults() {
const [query, setQuery] = useState('')
const [results, setResults] = useState([])
const [isPending, startTransition] = useTransition()
function handleChange(e) {
const value = e.target.value
// 立即更新输入框
setQuery(value)
// 标记搜索为过渡更新
startTransition(async () => {
const results = await search(value)
setResults(results)
})
}
return (
<div>
<input value={query} onChange={handleChange} />
{isPending ? <p>Searching...</p> : <ResultList results={results} />}
</div>
)
}
其他新 Hook
use API - 读取 Context
import { use } from 'react'
// 从 context 中读取值
const theme = use(ThemeContext)
// 从 promise 中读取值
const data = use(fetchData())
useId - 稳定的唯一 ID
import { useId } from 'react'
function PasswordFields() {
const id = useId()
return (
<>
<label htmlFor={`${id}-password`}>Password</label>
<input id={`${id}-password`} type="password" />
<label htmlFor={`${id}-confirm`}>Confirm</label>
<input id={`${id}-confirm`} type="password" />
</>
)
}
useSyncExternalStore - 订阅外部 Store
import { useSyncExternalStore } from 'react'
function useStore(store, selector) {
return useSyncExternalStore(
store.subscribe,
() => selector(store.getState()),
() => selector(store.getInitialState())
)
}
// 使用
function TodoList() {
const todos = useStore(todoStore, state => state.todos)
return <ul>{todos.map(...)}</ul>
}
改进的 Suspense
React 19 改进了 Suspense 的边界处理和错误恢复。
import { Suspense } from 'react'
function BlogPage() {
return (
<Suspense fallback={<Spinner />}>
<BlogPosts />
</Suspense>
)
}
async function BlogPosts() {
const posts = await fetchPosts()
return (
<div>
{posts.map(post => (
<Suspense key={post.id} fallback={<PostSkeleton />}>
<BlogPost id={post.id} />
</Suspense>
))}
</div>
)
}
Suspense with Error Boundary
import { ErrorBoundary } from 'react-error-boundary'
function App() {
return (
<ErrorBoundary
fallback={
<div>
<h2>Something went wrong</h2>
<button onClick={() => window.location.reload()}>
Retry
</button>
</div>
}
>
<Suspense fallback={<Spinner />}>
<BlogPage />
</Suspense>
</ErrorBoundary>
)
}
迁移指南
1. 升级依赖
npm install react@19 react-dom@19
npm install -D @types/react@19 @types/react-dom@19
2. 更新 JSX Transform
// 移除 React 导入(不再需要)
// ❌ 旧写法
import React from 'react'
export default function App() {
return <div />
}
// ✅ 新写法
export default function App() {
return <div />
}
3. 更新渲染 API
// ❌ ReactDOM.render 已废弃
import ReactDOM from 'react-dom'
ReactDOM.render(<App />, document.getElementById('root'))
// ✅ 使用 createRoot
import { createRoot } from 'react-dom/client'
const root = createRoot(document.getElementById('root'))
root.render(<App />)
4. 过滤掉的 PropTypes
// React 19 不再在运行时检查 PropTypes
// 考虑使用 TypeScript 替代
interface ButtonProps {
label: string
onClick: () => void
}
function Button({ label, onClick }: ButtonProps) {
return <button onClick={onClick}>{label}</button>
}
总结
React 19 是一次重大更新,带来了许多强大的新功能。Server Components 让我们能够构建更快速的应用,Actions 简化了表单处理,新的 Hook 提供了更好的用户体验。
关键要点
- Server Components 减少客户端 JavaScript
- Actions 简化表单和异步操作
- useOptimistic 提供即时 UI 反馈
- 改进的 Suspense 提供更好的加载体验
- React Compiler 自动优化性能
学习路径
- 先掌握 Server Components 的概念
- 学习 Actions 和相关 Hook
- 理解 useOptimistic 的使用场景
- 实践 Suspense 边界处理
- 启用 React Compiler 并验证优化效果