Next.js中使用SWR提交评论后如何即时刷新评论列表数据
问题根本原因
你提交评论后调用全局mutate时使用的缓存key,和评论列表组件中SWR请求的缓存key不匹配,导致重验证广播没有命中评论列表的缓存条目。
- 表单中调用的是
mutate('/api/comments') - 评论列表用的SWR key是
/api/comments/${postId}
只有当页面重新获得焦点时,SWR默认的焦点重验证机制才会自动触发请求拉取最新数据,这就是你只有失焦后再回来才看到新评论的原因。
解决方案
方案1:匹配精确key(首选,性能最优)
首先确保你的评论表单组件可以拿到当前所属帖子的postId参数,提交评论后直接调用对应key的重验证即可:
// 表单组件中修改postData方法,替换原有的mutate调用 const postData = async (form) => { setLoading(true); await axios.post('/api/comments', form); // 替换为和评论列表一致的key mutate(`/api/comments/${postId}`); setLoading(false); }
方案2:模糊匹配批量重验证(适合多帖子评论场景)
如果你的页面同时存在多个帖子的评论列表,且表单无法获取具体的postId,可以用SWR的函数匹配模式触发所有评论相关缓存的重验证:
mutate((key) => typeof key === 'string' && key.startsWith('/api/comments/'))
方案3:添加乐观更新(可选,优化体验)
如果想要实现提交后立即显示评论,不需要等接口请求返回,可以添加乐观更新逻辑:
const postData = async (form) => { setLoading(true); const commentKey = `/api/comments/${postId}`; // 先更新本地缓存,不立即触发重验证 mutate(commentKey, (oldData) => { const newComment = { ...form, _id: Date.now(), // 临时id createdAt: new Date(), userData: [ // 填入当前登录用户的信息 { name: 当前用户名, photoUrl: 当前用户头像 } ] } return [[newComment, ...(oldData?.[0] || [])]] }, false); try { await axios.post('/api/comments', form); } finally { // 请求完成后触发重验证对齐服务端数据 mutate(commentKey); setLoading(false); } }
额外优化建议
你的评论列表渲染代码可以添加可选链判断,避免无评论时出现报错,另外注意原代码中postId传值疑似错误,可以检查修正:
{comments?.[0]?.map((comment) => ( <Comment id={comment._id} key={comment._id} date={comment.createdAt} postId={comment.postId} // 原代码写的是comment._id,属于错误传值 comment={comment.comment} name={comment.userData[0].name} photoUrl={comment.userData[0].photoUrl} /> ))}
内容的提问来源于stack exchange,提问作者Ray Purchase
相关产品推荐
相关产品推荐

