useTransition 与 useOptimistic
Source: Dev.to

动态二人组:管理过程 vs. 管理感知
要实现“速度幻觉”,你需要两种不同的工具:
useTransition– 处理后台工作。它防止浏览器卡死,并告诉你是否有工作在进行(isPending)。useOptimistic– 处理即时视觉反馈。它立即更新 UI,假设后台工作会成功。
场景示例:“点赞”按钮
想象用户点击文章的“点赞”按钮。
-
没有乐观 UI:
用户点击 → 等待 1 秒 → 数字上升。(感觉迟缓)。 -
有乐观 UI:
用户点击 → 数字立即上升 → 服务器在后台同步。(感觉流畅)。
标准做法(仅 useTransition)
这里我们依赖服务器返回新的点赞数。useTransition 只用于显示加载指示,让用户知道有操作在进行。
体验: 用户点击 → 出现加载指示 → 加载指示消失并更新数字。
'use client';
import { useTransition } from 'react';
import { incrementLike } from './actions'; // Server Action
export default function StandardLikeButton({ likeCount }) {
const [isPending, startTransition] = useTransition();
const handleClick = () => {
startTransition(async () => {
// 1. Wait for the server to finish
await incrementLike();
// 2. UI updates after the server responds and the page re‑renders
});
};
return (
{/* Show a loading state because we don't have the new data yet */}
{isPending ? 'Updating...' : `♥ ${likeCount} Likes`}
);
}
幻觉做法(useTransition + useOptimistic)
我们预测未来。UI 立即更新,而服务器请求在后台运行。useTransition 保持应用响应;useOptimistic 提供即时的视觉变化。
体验: 用户点击 → 数字立即更新(不需要加载指示)。
'use client';
import { useOptimistic, useTransition } from 'react';
import { incrementLike } from './actions';
export default function OptimisticLikeButton({ likeCount }) {
// Optimistic state: real data + reducer to calculate the "fake" new state
const [optimisticLikes, addOptimisticLike] = useOptimistic(
likeCount,
(currentState, optimisticValue) => currentState + optimisticValue
);
const [isPending, startTransition] = useTransition();
const handleClick = () => {
startTransition(async () => {
// 1. ILLUSION: Update the UI immediately
addOptimisticLike(1);
// 2. REALITY: Perform the actual server request in the background
// If this fails, React automatically rolls back the optimistic state!
await incrementLike();
});
};
return (
{/* Display the optimistic (predicted) value immediately */}
♥ {optimisticLikes} Likes
);
}
关键差异概览
| 功能 | useTransition | useOptimistic |
|---|---|---|
| 主要目标 | 防止 UI 冻结;跟踪“加载”状态 | 在服务器确认前立即显示结果 |
| 用户体验 | “请稍等…”(真实的延迟) | “完成!”(即时满足) |
| 数据来源 | 等待服务器返回的数据 | 客户端预测 |
| 服务器失败时 | 应用保持在之前状态或显示错误 | UI 会自动回滚到正确的服务器状态 |
为什么要一起使用?
useOptimistic 在没有 useTransition(或包装了 transition 的 Server Actions)时几乎没有意义。
useOptimistic处理数据(例如显示 101 个赞而不是 100)。useTransition处理执行(确保按钮点击时页面不会卡死,直到请求发送到服务器)。
两者结合,能够提供快速、流畅的用户体验。