📋 目錄
React 19.2 沒有讓你的應用跑得更快——它讓你寫的程式碼更少。這篇文章從「簡化」的角度,完整解析 React 19.2 的三個核心改動,以及它們對日常開發的實際影響。
前言:React 的重心轉移了
過去幾年,React 的更新重點幾乎都是效能:Virtual DOM 優化、Concurrent Mode、Fiber 架構、Server Components。這些改動很了不起,但大多數開發者感受到的,其實是「學習曲線變陡了」。
React 19.2 不一樣。它的核心命題是減少樣板程式碼、降低認知負擔。你不需要懂 Concurrent Mode 也能用好這些功能。
這個轉變,其實是 React 團隊對「正確答案」的重新定義。效能優化可以靠框架自動處理,但開發者的心智負擔,終究需要人為介入才能減少。
1. useOptimistic:自動記住上次的状态
useOptimistic 並不是 React 19.2 新出的 hook——它在 React 19.0 就已經存在。但 19.2 帶來了一個關鍵的改進:自動記住(auto-remember)。
舊的麻煩:手動管理暫存狀態
在 React 19.0 的 useOptimistic 實現裡,你需要自己維護一個「樂觀更新」的狀態池。當伺服器回應錯誤時,你得手動把狀態回復到上一個版本:
// React 19.0 的麻煩之處
import { useOptimistic, useState } from 'react';
import { updateUsername } from './actions';
function UsernameForm() {
const [username, setUsername] = useState('');
const [optimisticUsername, setOptimisticUsername] = useOptimistic(username);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
// 手動設定 optimistic 狀態
const tempUsername = username;
setOptimisticUsername(username); // 立即顯示
try {
const newUsername = await updateUsername(username);
setUsername(newUsername);
} catch (error) {
// 錯誤時:需要自己回復,還要告訴使用者失敗了
setOptimisticUsername(tempUsername);
alert('更新失敗,請重試');
}
}
return (
<form onSubmit={handleSubmit}>
<input
value={optimisticUsername} // 樂觀更新:立馬看到結果
onChange={(e) => setUsername(e.target.value)}
/>
<button type="submit">更新</button>
</form>
);
}
問題在於:你得自己處理「回復」邏輯。當多個並發的 optimistic 更新同時發生時,手動管理會快速失控。
React 19.2 的 auto-remember:讓框架處理這些瑣事
React 19.2 的 useOptimistic 現在可以自動記住上次的成功狀態,並在錯誤發生時自動回復:
// React 19.2:更簡潔的寫法
import { useOptimistic } from 'react';
import { updateUsername } from './actions';
function UsernameForm() {
const [username, setUsername] = useState('');
// React 19.2:auto-remember 讓你不需要自己維護 optimistic state
const [optimisticUsername, setOptimisticUsername] = useOptimistic(
username, // 當前的真實狀態
(currentState, newValue) => newValue // 樂觀更新時如何轉換
);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
// 直接更新,React 會自動處理 optimistic state
// 不需要 try/catch、不需要自己回復狀態
setOptimisticUsername(username);
// 這個 action 現在會自動回復(如果失敗)
const result = await updateUsername(username);
if (result.ok) {
setUsername(result.newUsername);
}
// 失敗了?React 自動幫你回復,UI 狀態不用自己管
}
return (
<form onSubmit={handleSubmit}>
<input
value={optimisticUsername} // 樂觀更新
onChange={(e) => setUsername(e.target.value)}
/>
<button type="submit">更新</button>
</form>
);
}
這個改動的價值:當你同時擁有多個並發的 optimistic 更新時,auto-remember 讓 React 自己處理「哪個版本是正確的」這個問題。你只需要專心處理成功和失敗的商業邏輯,狀態管理的細節交給框架。
實際場景:電子商城的庫存扣減
電子商城中,使用者點擊「加入購物車」後,我們希望立即看見商品被加入,但實際的庫存扣減是在後端處理。如果扣減失敗(例如庫存不足),使用者應該看到商品被移除。
React 19.0 需要你自己寫這段邏輯:
// React 19.0:失敗邏輯自己處理
function AddToCartButton({ productId, stock }: { productId: string; stock: number }) {
const [cartCount, setCartCount] = useState(0);
const [optimisticCount, setOptimisticCount] = useOptimistic(cartCount);
async function handleAddToCart() {
const previousCount = cartCount;
setOptimisticCount(cartCount + 1); // 立即加一
const result = await addToCart(productId);
if (!result.ok) {
// 手動回復
setOptimisticCount(previousCount);
toast.error(result.error);
} else {
setCartCount(result.cartCount);
}
}
return (
<button onClick={handleAddToCart}>
加入購物車({optimisticCount}/{stock})
</button>
);
}
React 19.2 簡化為:
// React 19.2:auto-remember 處理回復邏輯
function AddToCartButton({ productId, stock }: { productId: string; stock: number }) {
const [cartCount, setCartCount] = useState(0);
const [optimisticCount, updateOptimisticCount] = useOptimistic(
cartCount,
(currentCount) => currentCount + 1
);
async function handleAddToCart() {
updateOptimisticCount(); // React 自動暫存,自動回復
const result = await addToCart(productId);
if (result.ok) {
setCartCount(result.cartCount);
}
// 失敗了?React 自動回復,不需要自己寫回復邏輯
}
return (
<button onClick={handleAddToCart}>
加入購物車({optimisticCount}/{stock})
</button>
);
}
2. useActionState:表單處理的進一步簡化
useActionState(前身是 React 19.0 的 useFormState)是 React 對表單處理的官方答案。React 19.2 在這個 hook 上做了兩個重要的簡化。
改進一:跨元件共享 action 狀態
過去,useActionState 的狀態是綁定在單一元件實例上的。如果你想在多個地方共享同一個 action 的狀態(例如在表單錯誤時,旁邊的 Summary 元件也要顯示錯誤訊息),就得透過 Context 或其他方式自己架構。
React 19.2 讓 useActionState 的狀態可以跨元件共享:
// React 19.2:action 狀態可以跨元件共享
import { useActionState } from 'react';
import { submitOrder } from './actions';
// 定義 action
const submitOrderAction = async (previousState: OrderState, formData: FormData) => {
const validated = validateOrder(formData);
if (!validated.ok) {
return { error: validated.message, success: false };
}
const result = await submitOrder(validated.data);
return { error: null, success: true, orderId: result.orderId };
};
// 表單元件:使用 action
function OrderForm() {
const [state, formAction, isPending] = useActionState(
submitOrderAction,
{ success: false, error: null, orderId: null }
);
return (
<form action={formAction}>
<input name="email" type="email" required />
<input name="productId" type="hidden" value="ITEM_001" />
{state.error && <p className="error">{state.error}</p>}
<button type="submit" disabled={isPending}>
{isPending ? '處理中...' : '確認訂單'}
</button>
</form>
);
}
// 另一個元件:同一個 action 狀態,不需要自己傳遞
function OrderConfirmation() {
const [, , isPending] = useActionState(submitOrderAction, null);
// ^ React 19.2 允許傳 null 作為初始狀態(當 action 只用於共享狀態時)
// 這個元件只看 isPending,不需要其他狀態
return isPending ? <LoadingSpinner /> : null;
}
改進二:內建錯誤邊界(Error Boundary)整合
React 19.2 的 useActionState 現在自動處理 Action 的錯誤,不需要自己包 try/catch:
import { useActionState } from 'react';
import { submitFeedback } from './actions';
function FeedbackForm() {
const [state, formAction] = useActionState(submitFeedback, {
submitted: false,
error: null,
});
// React 19.2:錯誤自動寫入 state,不需要自己 catch
return (
<form action={formAction}>
<textarea name="feedback" required />
{state.error && <p role="alert">{state.error}</p>}
{state.submitted && <p>感謝回饋!</p>}
<button type="submit">送出</button>
</form>
);
}
關於 Server Actions 的基礎概念,請參考 React Server Actions 完整指南。本文專注於 React 19.2 的進階應用差異。
3. Server Actions 的改進:更少的 boilerplate
Server Actions 在 React 19.0 首次引入時,需要透過 use server 指令明確定義。React 19.2 簡化了這個流程,特別是在**漸進式遷移(progressive enhancement)**場景。
直接在 Client Component 使用 Server Function
React 19.0 要求 Server Actions 必須定義在 Server Component 檔案(或頂層 Module)中:
// React 19.0:需要在 server 檔案中明確標記
// actions.ts(server file)
'use server';
export async function createPost(formData: FormData) {
const title = formData.get('title') as string;
await db.post.create({ data: { title } });
revalidatePath('/posts');
}
React 19.2 允許你在 Client Component 內直接定義 async function,並透過 useActionState 使用:
// React 19.2:更簡潔的寫法
'use client';
import { useActionState } from 'react';
function CreatePostForm() {
const [state, formAction] = useActionState(
// 直接在 Client Component 內定義 Server Action
async (prevState: unknown, formData: FormData) => {
'use server'; // React 19.2 允許在 function 內使用這個指令
const title = formData.get('title') as string;
await db.post.create({ data: { title } });
revalidatePath('/posts');
return { ok: true };
},
{ ok: false }
);
return (
<form action={formAction}>
<input name="title" required />
<button type="submit">發布文章</button>
</form>
);
}
這個改動的意義:對於簡單的 CRUD 操作,你不再需要為了建立一個 Server Action 而建立一個獨立的 server 檔案。漸進式遷移變得更容易——可以先在 Client Component 內用 inline 'use server' 實驗,確認沒問題後再重構到獨立的 server 模組。
對開發效率的實際影響
React 19.2 的三個簡化,對日常開發的影響可以用三個場景說明:
| 場景 | React 19.0 的寫法 | React 19.2 的寫法 |
|---|---|---|
| 樂觀更新失敗回復 | 需要自己寫 try/catch + 狀態回復 | React auto-remember 自動處理 |
| 跨元件共享表單狀態 | 需要 Context 或 Zustand | useActionState(null, action) 直接共享 |
| 簡單 Server Action | 需要獨立 server 檔案 + 'use server' 頂層標記 | Client Component 內可用 'use server' inline |
常見問題
Q:React 19.2 支援哪些版本?
React 19.2 需要 React 19.x 的環境。它不相容 React 18。如果你的專案還在 React 18,升級到 React 19 是使用這些功能的前提。
Q:auto-remember 適合所有場景嗎?
不完全是。auto-remember 適用於「簡單的單一狀態更新」。當你的 optimistic 更新涉及複雜的商業邏輯(例如庫存扣減需要同時更新多個地方的數字),手動管理仍然更安全。
Q:inline 'use server' 會影響效能嗎?
不會。'use server' 是一個靜態標記,它告訴 React 這個 function 需要在伺服器執行。即使寫在 Client Component 檔案裡,React 也會把它提取到獨立的 server bundle 中。
總結:React 19.2 的核心訊息
React 19.2 的主題是「讓框架處理繁瑣的事」:
- useOptimistic auto-remember:失敗回復不用自己寫
- useActionState 跨元件共享:狀態共享更直覺
- inline
'use server':簡單 Server Actions 不需要獨立檔案
這三個改動都指向同一個方向:框架吸收更多樣板程式碼,讓開發者專注在商業邏輯。對於每天都在寫 React 的工程師來說,這些「簡化」累積起來,就是實實在在的時間節省。
本文屬於「React 19 新功能」系列文章。