React 19 新特性完全指南:Actions、use()、Server Components 與編譯器最佳化
前端工程(更新於 2026年5月6日)
React 19:框架級的範式升級
React 19 不只是 API 更新,而是從「庫」到「全棧框架」的定位轉變。Server Components、Actions、Compiler 三大特性重新定義了 React 應用的寫法。
| 特性 | 解決的問題 | 影響範圍 |
|---|---|---|
| Form Actions | 表單提交的樣板程式碼 | 所有表單互動 |
| use() Hook | 條件式資料載入 | 資料獲取模式 |
| Server Components | 客戶端包體積 | 全架構 |
| React Compiler | 手動 memo 最佳化 | 效能 |
| ref as prop | forwardRef 樣板程式碼 | 元件 API |
| Document Metadata | SEO/head 管理 | SSR 應用 |
一、Form Actions:告別表單樣板程式碼
傳統寫法
function LoginForm() {
const [pending, setPending] = useState(false);
const [error, setError] = useState(null);
async function handleSubmit(e) {
e.preventDefault();
setPending(true);
setError(null);
try {
const formData = new FormData(e.target);
await login(formData.get('email'), formData.get('password'));
} catch (err) {
setError(err.message);
} finally {
setPending(false);
}
}
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" />
<input name="password" type="password" />
<button disabled={pending}>{pending ? '登入中...' : '登入'}</button>
{error && <p>{error}</p>}
</form>
);
}
React 19 寫法
async function loginAction(formData) {
// 直接在 Server 上執行,無需手動管理 pending/error
await login(formData.get('email'), formData.get('password'));
}
function LoginForm() {
return (
<form action={loginAction}>
<input name="email" type="email" />
<input name="password" type="password" />
<SubmitButton />
</form>
);
}
// useActionStatus 自動追蹤提交狀態
function SubmitButton() {
const { pending } = useActionStatus();
return <button disabled={pending}>{pending ? '登入中...' : '登入'}</button>;
}
減少程式碼量:約 60%。不再需要 onSubmit、preventDefault、手動 pending/error 狀態。
useActionState:管理表單狀態
function LoginForm() {
const [state, formAction, isPending] = useActionState(
async (prevState, formData) => {
try {
await login(formData.get('email'), formData.get('password'));
return { success: true };
} catch (err) {
return { error: err.message };
}
},
null
);
return (
<form action={formAction}>
<input name="email" type="email" />
<input name="password" type="password" />
<button disabled={isPending}>登入</button>
{state?.error && <p className="error">{state.error}</p>}
</form>
);
}
二、use() Hook:條件式資料載入
use() 是 React 第一個可以在條件語句和迴圈中呼叫的 Hook。
讀取 Promise
function UserProfile({ userPromise }) {
// 可以在條件中使用!
if (showProfile) {
const user = use(userPromise);
return <h1>{user.name}</h1>;
}
return null;
}
讀取 Context
function ThemeToggle() {
// 之前必須用 useContext,現在可以用 use
const theme = use(ThemeContext);
return <button onClick={toggle}>{theme}</button>;
}
Suspense 整合
function UserPage({ userPromise }) {
return (
<Suspense fallback={<Spinner />}>
<UserProfile userPromise={userPromise} />
</Suspense>
);
}
function UserProfile({ userPromise }) {
const user = use(userPromise);
return <div>{user.name}</div>;
}
三、Server Components 正式穩定
Server vs Client 元件
// Server Component(預設)
// - 在服務端渲染,不傳送 JS 到客戶端
// - 可以直接存取資料庫、檔案系統
// - 不能使用 useState、useEffect、事件處理
async function BlogList() {
const posts = await db.query('SELECT * FROM posts');
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<h2>{post.title}</h2>
<LikeButton postId={post.id} /> {/* Client Component */}
</li>
))}
</ul>
);
}
// Client Component
'use client';
// - 在客戶端渲染(也可 SSR)
// - 可以使用所有 Hook
// - 打包傳送到客戶端
function LikeButton({ postId }) {
const [liked, setLiked] = useState(false);
return <button onClick={() => setLiked(!liked)}>❤️</button>;
}
Server Actions
'use server';
async function createPost(formData) {
const title = formData.get('title');
const content = formData.get('content');
await db.insert('posts', { title, content });
revalidatePath('/blog');
}
// Client 元件中使用 Server Action
function NewPostForm() {
return (
<form action={createPost}>
<input name="title" />
<textarea name="content" />
<button type="submit">發布</button>
</form>
);
}
四、React Compiler:自動效能最佳化
React Compiler(原 React Forget)自動插入 memo 邏輯,開發者不再需要手動使用 useMemo、useCallback、memo。
編譯前
function ExpensiveComponent({ items, filter }) {
// 開發者手動最佳化
const filtered = useMemo(
() => items.filter(i => i.category === filter),
[items, filter]
);
const handleClick = useCallback((id) => {
console.log(id);
}, []);
return <List items={filtered} onClick={handleClick} />;
}
編譯後(自動最佳化)
function ExpensiveComponent({ items, filter }) {
// 直接寫,編譯器自動 memoize
const filtered = items.filter(i => i.category === filter);
const handleClick = (id) => console.log(id);
return <List items={filtered} onClick={handleClick} />;
}
啟用 Compiler
// next.config.js
const nextConfig = {
experimental: {
reactCompiler: true, // 或 'unstable' 獲取最新特性
},
};
Compiler 的限制
| 不自動最佳化的場景 | 原因 |
|---|---|
| 修改傳入的 props/mutable 物件 | 副作用無法追蹤 |
| 在 Hook 外部建立的閉包 | 生命週期不明確 |
使用 arguments 物件 |
非標準用法 |
五、ref 作為 prop:告別 forwardRef
React 18 寫法
const Input = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
React 19 寫法
function Input({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
// 使用
<Input ref={inputRef} placeholder="請輸入" />;
六、Document Metadata
React 19 原生支援 <title>、<meta>、<link> 在元件中宣告:
function BlogPost({ post }) {
return (
<>
<title>{post.title}</title>
<meta name="description" content={post.excerpt} />
<link rel="canonical" href={`https://example.com/blog/${post.slug}`} />
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
</>
);
}
React 自動將這些標籤提升到 <head> 中,不同路由的 metadata 自動去重替換。
七、其他改進
useOptimistic:樂觀更新
function LikeButton({ postId, initialLiked }) {
const [liked, addOptimisticLike] = useOptimistic(initialLiked);
async function handleLike() {
addOptimisticLike(true); // 立即顯示點讚
await likePost(postId); // 後臺同步
}
return <button onClick={handleLike}>{liked ? '❤️' : '🤍'}</button>;
}
useSyncExternalStore 改進
支援訂閱 getSnapshot 返回不同值但語義等價的 store(如帶快取的資料獲取)。
Custom Elements 完整支援
React 19 正確處理 Custom Elements 的屬性和事件:
<my-custom-element someProp="value" onCustomEvent={handler} />
遷移清單
| 變更 | 影響 | 行動 |
|---|---|---|
forwardRef → ref prop |
所有使用 forwardRef 的元件 | 遷移 |
useMemo/useCallback |
手動 memo | 啟用 Compiler 後逐步移除 |
onSubmit → action |
表單元件 | 重構為 Actions |
useContext → use() |
Context 消費 | 可選遷移 |
ref.current.cleanup() |
ref callback 清理 | 新模式 |
| 字串 ref 廢棄 | 舊程式碼 | 遷移為 callback/object ref |
Codemod 工具
npx react-codemod@latest react-19
自動處理大部分 Breaking Changes,包括 forwardRef 遷移、字串 ref 替換等。
#React#React 19#Server Components#前端框架