React19 useOptimistic 用法

用法

乐观更新

  • 发起异步请求时,先假设请求会成功
  • 立即更新 UI 给用户反馈
  • 若请求最终失败,再将 UI 恢复到之前的状态

const [optimisticState, addOptimistic] = useOptimistic(state, updateFn)

参数
state:实际值,可以是 useStateuseReduceruseContextprops
updateFn:纯函数

  • currentState
  • optimisticValue

返回值
optimisticState:乐观值

  • 正常情况下:和 state 实际值一致
  • 调用 addOptimistic 后,是 updateFn 的返回值

addOptimistic:调用updateFn,接收任意类型的 optimisticValue

注意点

  1. 要在 form ActionstartTransition 里面调用 addOptimistic
  2. 异步操作结束(无论成功还是失败),乐观值都会自动恢复成 state
    异步操作成功,需要手动 setState 更新实际值,从而更新 useOptimisticstate
    异步操作失败,不用管

测试代码

javascript 复制代码
import React, { useState, useOptimistic, startTransition } from "react";

// 模拟异步点赞请求,考虑请求失败的情况
const asyncLikePost = (postId) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 模拟 50% 的失败概率
      if (Math.random() < 0.5) {
        reject(new Error("点赞失败"));
      } else {
        resolve();
      }
    }, 3000);
  });
};

const Post = ({ post }) => {
  const [likes, setLikes] = useState(post.likes);
  const [optimisticLikes, addOptimisticLikes] = useOptimistic(
    likes,
    (currentLikes, optimisticValue) => currentLikes + 1
  );
  const [error, setError] = useState(null);

  const handleLike = function handleLike() {
    startTransition(async () => {
      addOptimisticLikes();

      try {
        await asyncLikePost(post.id);
        setLikes((prevLikes) => prevLikes + 1);
        setError(null);
      } catch (error) {
        setError(error.message);
      }
    });
  };

  return (
    <div>
      <p>{post.title}</p>
      <p>实际点赞数: {likes}</p>
      <p>乐观点赞数: {optimisticLikes}</p>
      {error && <p style={{ color: "red" }}>{error}</p>}

      <button onClick={handleLike}>点赞</button>
    </div>
  );
};

const PostList = () => {
  const posts = [
    { id: 1, title: "帖子1", likes: 10 },
    { id: 2, title: "帖子2", likes: 20 },
  ];

  return (
    <div>
      {posts.map((post) => (
        <Post key={post.id} post={post} />
      ))}
    </div>
  );
};

export default function App() {
  return (
    <div>
      <h1>帖子列表</h1>
      <PostList />
    </div>
  );
}
相关推荐
牛仔只喝牛奶14 小时前
多端跨端技术选型:小程序 + H5 + App 的两栈拆分落地
react native·react.js
wear工程师17 小时前
setState 到底是不是异步的?这题从 React 16 问到 18,标准答案早就变了
react.js·面试
wanghowie19 小时前
LangGraph4j 落地(二)— ReAct 多步工具与 trace 扩展
前端·react.js·前端框架
csj5020 小时前
前端基础之《React(11)—state声明式》
前端·react.js
张元清21 小时前
React useLocalStorage Hook:SSR 安全的持久化状态(2026)
javascript·react.js
析数塔21 小时前
2026前端框架深度解析:React Compiler、Angular Zoneless、Vue 3.5重写游戏规则
前端·vue.js·react.js
杖雍皓21 小时前
没有服务器如何构建现代 Web 应用:平台选型与组合策略
运维·服务器·前端·react.js·github·netlify·vercel
sun_weitao1 天前
微前端框架之qiankun 怎么用?vue3+vite+qiankun 和 react + qiankun
前端·react.js·前端框架
名字还没想好☜2 天前
React useEffect 依赖数组踩坑:闭包陷阱与清理函数
前端·javascript·react.js·react·useeffect
我是大卫2 天前
【图】React源码解析-第四部分:事件与跨层传递
react.js·源码