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>
  );
}
相关推荐
cn_mengbei1 天前
用React Native开发OpenHarmony应用:Reanimated共享元素过渡
javascript·react native·react.js
We་ct1 天前
React 性能优化精讲
前端·javascript·react.js·性能优化·前端框架·html·浏览器
光影少年1 天前
前端在页面渲染优化和组件优化经验?
前端·vue.js·react.js·前端框架
Wect2 天前
React 性能优化精讲
前端·react.js·性能优化
光影少年2 天前
react性能优化比较好的办法有哪些?
前端·react.js·性能优化
Ww.xh2 天前
Figma设计稿转React代码:ClaudeCode+MCP实战教程
前端·react.js·figma
朝阳392 天前
react【实战】自定义下拉框、单选、多选、输入框
前端·javascript·react.js
IT枫斗者3 天前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
倾颜3 天前
React 19 源码主线拆解 04:Fiber 到底是什么,React 为什么需要 Fiber?
前端·react.js·源码阅读
老王以为3 天前
为什么 React 和 Vue 不一样?
前端·vue.js·react.js