会持续跟新技术干货,感谢大家支持,欢迎点赞、评论、留言。公众号同名【码间舞】
React是一个非常收欢迎的前端框架,国内外的一大群开发者用户,截止本文写作时为止,react的官方star是237K,周下载量也是稳步上升,在前端三大框架里面是最高的。而作为最受欢迎的框架之一,他的每次更新也牵动着万千开发者的内心。
我会整理出一些react19新的特性、新的api给大家详细分析以及其实战用法,不足之处还望各位大佬指出,一起探讨进步,感谢大家的支持~
今天要讲的是react19的新特性useOptimistic这个新的hooks。
1 useOptimistic简介
这是官方给出的解释:
记得贴图!!!!
optimistic意思是乐观的,这里非常明显,只要一切正常不发生然后问题,提前更新的值就会是期待的那个值,具体我们接着看。
2 问题和业务场景
相信大家开发过程中都遇到过一个问题,比如社交媒体类型的站点里都会有点赞、收藏等交互性极高的操作,我们通常会在点击之后去请求后端的接口,当接口返回后我们再做页面交互,比如点赞+1或者收藏icon的替换等操作在这个过程中如果网络有问题,或者后端反应不及时,那么用户会发现点击之后会发现没有反应,还会怀疑是不是没有点到会再次尝试点击...,那么前端同学们考验你们的时候来了,你的防抖、节流等优化做到位了吗【手动狗头】!
3 useOptimistic来救火
面对以上场景,如果我们使用react19,那么我们可以立即在UI上显示更新(乐观更新),同时后台处理实际API请求
废话不多说上代码:
首先我们定义好一个异步请求的方法likePost(postId, increment),他负责请求后台api接口,这里用定时器mock
// 模拟API请求
const likePost = async (postId, increment) => {
return new Promise((resolve, reject) => {
// 模拟网络延迟(1-2秒)
const delay = Math.random() * 1000 + 1000;
setTimeout(() => {
// 模拟10%的失败率
const shouldFail = Math.random() < 0.1;
if (shouldFail) {
reject(new Error('请求失败,请重试'));
} else {
console.log(`成功${increment > 0 ? '点赞' : '取消点赞'}帖子 ${postId}`);
resolve();
}
}, delay);
});
};
接着是useOptimistic的核心功能:
- 创建乐观状态 optimisticLikes,它会在用户操作时立即更新
- 定义更新函数 updateOptimisticLikes,用于修改乐观状态
import { useState, useCallback } from 'react';
import { useOptimistic } from 'react';
const PostItem = ({ post }) => {
// 使用 useOptimistic 管理点赞状态
const [optimisticLikes, updateOptimisticLikes] = useOptimistic(
post.likes,
(currentLikes, delta) => {
// 确保点赞数不会低于0
const newLikes = currentLikes + delta;
return Math.max(newLikes, 0);
}
);
const [isPending, setIsPending] = useState(false);
const [error, setError] = useState(null);
const handleLike = useCallback(async () => {
setIsPending(true);
setError(null);
try {
// 乐观更新:立即增加点赞数
updateOptimisticLikes(1);
// 发送API请求
await likePost(post.id, 1);
} catch (err) {
// 请求失败:回滚到之前的状态
updateOptimisticLikes(-1);
setError(err.message);
} finally {
setIsPending(false);
}
}, [post.id, updateOptimisticLikes]);
const handleUnlike = useCallback(async () => {
if (optimisticLikes <= 0) return;
setIsPending(true);
setError(null);
try {
// 乐观更新:立即减少点赞数
updateOptimisticLikes(-1);
// 发送API请求
await likePost(post.id, -1);
} catch (err) {
// 请求失败:回滚到之前的状态
updateOptimisticLikes(1);
setError(err.message);
} finally {
setIsPending(false);
}
}, [post.id, optimisticLikes, updateOptimisticLikes]);
return (
<div className="post">
<h3>{post.title}</h3>
<p>{post.content}</p>
<div className="like-section">
<button
onClick={handleLike}
disabled={isPending}
className={isPending ? 'pending' : ''}
>
👍 点赞
</button>
<button
onClick={handleUnlike}
disabled={isPending || optimisticLikes <= 0}
className={isPending ? 'pending' : ''}
>
👎 取消
</button>
<div className="likes-count">
<span>{optimisticLikes}</span>
<span> 人点赞</span>
</div>
{error && <div className="error">{error}</div>}
</div>
</div>
);
};
const SocialMediaApp = () => {
const [posts] = useState([
{ id: 1, title: "React 19 发布啦!", content: "React 19 带来了许多令人兴奋的新特性...", likes: 42 },
{ id: 2, title: "学习 useOptimistic", content: "useOptimistic 是处理乐观更新的绝佳方式...", likes: 18 },
{ id: 3, title: "前端开发趋势", content: "2025年前端开发有哪些新趋势?一起来看看...", likes: 56 }
]);
return (
<div className="social-media-app">
<header>
<h1>社交媒体应用</h1>
<p>体验 React 19 的 useOptimistic 功能</p>
</header>
<div className="posts-container">
{posts.map(post => (
<PostItem key={post.id} post={post} />
))}
</div>
<div className="explanation">
<h3>useOptimistic 工作原理:</h3>
<ol>
<li>用户点击点赞按钮时,立即更新UI(乐观更新)</li>
<li>后台发送API请求到服务器</li>
<li>如果请求成功,状态保持更新</li>
<li>如果请求失败,自动回滚到之前的状态</li>
</ol>
<p>注:此演示模拟了10%的API失败率,体验失败时的自动回滚效果</p>
</div>
</div>
);
};
export default SocialMediaApp;
我们梳理一下点赞的逻辑:
- 用户点击点赞按钮时,立即调用 updateOptimisticLikes(1)
- 同时发起异步请求 likePost(post.id, 1)
- 如果请求成功,状态保持更新,无需修改
- 如果请求失败(模拟10%失败率),调用 updateOptimisticLikes(-1) 回滚状态
UI的显示逻辑是:
- 使用 isPending 状态显示加载效果
- 显示错误信息(当API请求失败时)
- 禁用按钮防止重复操作
4 与之前版本的区别
// React 18 实现方式
const [likes, setLikes] = useState(post.likes);
const [isPending, setIsPending] = useState(false);
const [error, setError] = useState(null);
const handleLike = async () => {
setIsPending(true);
setError(null);
// 保存当前状态以便回滚
const previousLikes = likes;
// 乐观更新
setLikes(prev => prev + 1);
try {
await likePost(post.id, 1);
} catch (err) {
// 请求失败,回滚到之前的状态
setLikes(previousLikes);
setError(err.message);
} finally {
setIsPending(false);
}
};
这样看,感觉好像18也挺简单的,不过在方法里多了previousLikes的中间状态,但是官方更推荐使用hooks来进行状态的管,主要好处是:
- 简化状态管理逻辑,无需手动保存之前的状态
- 更优雅的回滚机制,避免状态不一致问题
- 更好的性能优化,减少不必要的渲染
- 代码更简洁,逻辑更清晰
这个演示展示了 useOptimistic 如何显著改善需要即时 UI 反馈的交互体验,特别是在网络请求可能延迟或失败的场景中。
- React官方 useOptimistic