React19 useOptimistic 用法
用法
乐观更新
- 发起异步请求时,先假设请求会成功
- 立即更新 UI 给用户反馈
- 若请求最终失败,再将 UI 恢复到之前的状态
const [optimisticState, addOptimistic] = useOptimistic(state, updateFn)
参数
state
:实际值,可以是 useState
、useReducer
、useContext
、props
updateFn
:纯函数
currentState
optimisticValue
返回值
optimisticState
:乐观值
- 正常情况下:和
state
实际值一致 - 调用
addOptimistic
后,是updateFn
的返回值
addOptimistic
:调用updateFn
,接收任意类型的 optimisticValue
注意点
- 要在
form Action
或startTransition
里面调用addOptimistic
- 异步操作结束(无论成功还是失败),乐观值都会自动恢复成
state
异步操作成功,需要手动setState
更新实际值,从而更新useOptimistic
的state
异步操作失败,不用管
测试代码
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>);
}