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>
  );
}
相关推荐
渔舟唱晚@几秒前
React Native 从零开始完整教程(环境配置 → 国内镜像加速 → 运行项目)
javascript·react native·react.js
进取星辰12 小时前
16、路由守卫:设置魔法结界——React 19 React Router
前端·javascript·react.js
哟哟耶耶16 小时前
react-10样式模块化(./index.module.css, <div className={welcome.title}>Welcome</div>)
前端·javascript·react.js
苦夏木禾18 小时前
关于react19版本更新后部分组件无法正常使用的问题
javascript·react.js
qq_589568101 天前
react学习笔记2——基于React脚手架与ajax
笔记·学习·react.js·ajax
孙俊熙1 天前
react中封装一个预览.doc和.docx文件的组件
前端·react.js·前端框架
爱笑的眼睛112 天前
React Native 入门 jsx tsx 基础语法
javascript·react native·react.js
刺客-Andy2 天前
React 第三十六节 Router 中 useParams 的具体使用及详细介绍
前端·react.js·前端框架
哟哟耶耶2 天前
react-11使用vscode开发react相关扩展插件(相关的快捷生成)
javascript·vscode·react.js