人人都会AI编程

26.3 defineModel、defineProps 解构等语法糖

更新时间:2026-07-10

乐观更新(Optimistic Update)是指在服务端确认之前,先假设操作会成功并立即更新 UI,让用户感知不到网络延迟。如果后续服务端返回失败,再回滚到之前的状态。这种模式在点赞、收藏、评论等即时反馈场景中非常常见。

在 React 19 之前,实现乐观更新通常需要手动维护“临时状态 + 回滚逻辑”,或者借助 React Query、Redux 等外部库。React 19 提供了原生的 useOptimistic Hook,将这一模式固化为框架层的能力。

基本用法

useOptimistic 接收两个参数:

  1. 原始状态(通常是来自服务端或父组件的“真实数据”)
  2. 更新函数:定义如何基于当前状态和乐观值产出新的 UI 状态

它返回一个数组:

  • 乐观状态:在等待服务端响应期间立即展示给用户的状态
  • 添加乐观更新:一个函数,调用它时会立即应用更新函数,并在异步操作完成后自动恢复为原始状态
import { useOptimistic } from 'react';

function LikeButton({ initialLiked, initialCount, onToggle }) {
  // initialLiked 和 initialCount 来自服务端或父组件
  const [optimisticState, addOptimistic] = useOptimistic(
    { liked: initialLiked, count: initialCount },
    (currentState, newLiked) => ({
      liked: newLiked,
      count: newLiked ? currentState.count + 1 : currentState.count - 1,
    })
  );

  const handleClick = async () => {
    const newLiked = !optimisticState.liked;
    // 立即应用乐观更新
    addOptimistic(newLiked);
    // 发送真实请求
    try {
      await onToggle(newLiked);
    } catch {
      // 请求失败时,useOptimistic 会自动回滚到原始状态
      // 无需手动处理
    }
  };

  return (
    <button onClick={handleClick}>
      {optimisticState.liked ? '❤️ 已赞' : '🤍 点赞'} ({optimisticState.count})
    </button>
  );
}

核心思路是:先假设成功 → 立即更新 UI → 等待服务端确认。如果服务端操作失败(抛出异常),useOptimistic 会自动丢弃乐观更新,将状态恢复为最后一次未更新的原始值。

与 React 19 的 Server Actions 配合

React 19 的 Server Actions 可以直接与 useOptimistic 结合,实现端到端的乐观更新:

import { useOptimistic } from 'react';
import { toggleLikeAction } from './actions';

function Post({ post }) {
  const [optimisticPost, addOptimistic] = useOptimistic(
    post,
    (currentPost, newLiked) => ({
      ...currentPost,
      liked: newLiked,
      likesCount: newLiked ? currentPost.likesCount + 1 : currentPost.likesCount - 1,
    })
  );

  async function handleLike() {
    const newLiked = !optimisticPost.liked;
    addOptimistic(newLiked); // 乐观更新
    await toggleLikeAction(post.id, newLiked); // Server Action
  }

  return (
    <div>
      <h3>{optimisticPost.title}</h3>
      <button onClick={handleLike}>
        {optimisticPost.liked ? '❤️' : '🤍'} {optimisticPost.likesCount}
      </button>
    </div>
  );
}

如果 toggleLikeAction 在服务端执行失败,它会抛出错误,useOptimistic 自动将 optimisticPost 回滚到 post 的最新值,用户看到的点赞按钮会恢复到操作前的状态。

实际开发中的注意点

  1. 自动回滚机制

乐观更新只在发起 addOptimistic 的同步函数或异步函数的第一个 await 之前生效。一旦异步操作完成(无论成功或失败),React 都会根据传入的新原始状态重新计算 UI——如果原始状态已更新,则乐观状态自然与之一致;如果异步操作抛错,原始状态未变,则乐观状态被丢弃。因此不需要手动回滚。

  1. 不要直接修改原始状态

useOptimistic 返回的乐观状态是只读快照,不能直接赋值修改。所有变更都应通过 addOptimistic 进行。

  1. 复杂场景的组合使用

useOptimistic 可以和其他 Hook(如 useActionStateuseTransition)组合,处理表单提交、多步操作等复杂交互。它更多是一种展示层的即时反馈机制,底层仍然依赖真实状态更新来同步。

  1. 适用边界

对于确定性很高且用户对延迟敏感的操作(如点赞、拖拽排序、文本编辑),useOptimistic 是最佳选择。但对转账、订单提交等关键操作,建议谨慎使用乐观更新,或仅将其用于临时加载提示而非真实数据展示。

与传统实现方式的对比

| 传统方式 | useOptimistic |
|---------|---------------|
| 需要手动创建临时状态变量 | 框架自动管理乐观状态 |
| 需在 try-catch 中手动回滚 | 自动回滚,减少样板代码 |
| 状态逻辑散落在多个地方 | 状态更新逻辑集中在一个更新函数 |
| 需处理竞态条件(快速连续点击) | React 内部处理序列,保证状态一致性 |

useOptimistic 的出现,进一步强化了 React 19 作为“全栈框架核心库”的定位,让前端常见的用户体验优化模式变得内建且标准化。