当前位置: 首页 > news >正文

React删除评论逻辑:1、客户端立即更新UI(乐观更新)2、后台调用删除评论API(乐观消息Optimistic Message)

https://gitee.com/arnold_s/my-learning-test/blob/master/20250520_reactTest/01_easyReact/react-basic_pro/src/App_Day1-14.%E8%AF%84%E8%AE%BA%E6%A1%88%E4%BE%8B-%E5%88%A0%E9%99%A4%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0.js

文章目录

  • 原代码
  • 问:为什么删除评论是客户端调用过滤评论,而不是请求数据库删除,然后再从数据库获取最新评论列表呢?
    • 当前代码的实现方式(本地状态管理)
    • 两种方式的对比
      • 1. **本地过滤方式**(当前代码)
      • 2. **API删除方式**(你提到的方式)
    • 实际项目中的最佳实践
    • 总结

原代码

import'./App.scss'importavatarfrom'./images/bozai.png'import{useState}from'react'/** * 评论列表的渲染和操作 * * 1. 根据状态渲染评论列表 * 2. 删除评论 */// 评论列表数据constdefaultList=[{// 评论idrpid:3,// 用户信息user:{uid:'13258165',avatar:'',uname:'周杰伦',},// 评论内容content:'哎哟,不错哦',// 评论时间ctime:'10-18 08:15',like:88,},{rpid:2,user:{uid:'36080105',avatar:'',uname:'许嵩',},content:'我寻你千百度 日出到迟暮',ctime:'11-13 11:29',like:88,},{rpid:1,user:{uid:'30009257',avatar,uname:'黑马前端',},content:'学前端就来黑马',ctime:'10-19 09:00',like:66,},]// 当前登录用户信息constuser={// 用户iduid:'30009257',// 用户头像avatar,// 用户昵称uname:'黑马前端',}/** * 导航 Tab 的渲染和操作 * * 1. 渲染导航 Tab 和高亮 * 2. 评论列表排序 * 最热 => 喜欢数量降序 * 最新 => 创建时间降序 */// 导航 Tab 数组consttabs=[{type:'hot',text:'最热'},{type:'time',text:'最新'},]// 2、使用useEffect 监听评论列表数据的变化// 3、使用useRef 管理评论列表的滚动位置// 4、使用useCallback 管理评论列表的滚动位置// 5、使用useMemo 管理评论列表的滚动位置// 6、使用useContext 管理评论列表的滚动位置// 7、使用useReducer 管理评论列表的滚动位置constApp=()=>{// 渲染评论列表// 1、使用useState 管理评论列表数据const[commentList,setCommentList]=useState(defaultList)// 删除评论consthandleDelete=(rpid)=>{// 过滤掉要删除的评论// 使用filter 方法过滤掉要删除的评论// filter 方法会返回一个新数组,新数组中不包含要删除的评论// 新数组中的元素是原数组中除了要删除的评论以外的所有元素// 使用setCommentList 方法更新评论列表数据setCommentList(commentList.filter(item=>item.rpid!==rpid))}return(<div className="app">{/* 导航 Tab */}<div className="reply-navigation"><ul className="nav-bar"><li className="nav-title"><span className="nav-title-text">评论</span>{/* 评论数量 */}<span className="total-reply">{10}</span></li><li className="nav-sort">{/* 高亮类名: active */}<span className='nav-item'>最新</span><span className='nav-item'>最热</span></li></ul></div><div className="reply-wrap">{/* 发表评论 */}<div className="box-normal">{/* 当前用户头像 */}<div className="reply-box-avatar"><div className="bili-avatar"><img className="bili-avatar-img"src={avatar}alt="用户头像"/></div></div><div className="reply-box-wrap">{/* 评论框 */}<textarea className="reply-box-textarea"placeholder="发一条友善的评论"/>{/* 发布按钮 */}<div className="reply-box-send"><div className="send-text">发布</div></div></div></div>{/* 评论列表 */}<div className="reply-list">{/* 评论项 */}{commentList.map(item=>(<div key={item.rpid}className="reply-item">{/* 头像 */}<div className="root-reply-avatar"><div className="bili-avatar"><img className="bili-avatar-img"alt=""src={item.user.avatar||'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/72x72/1f464.png'}/></div></div><div className="content-wrap">{/* 用户名 */}<div className="user-info"><div className="user-name">{item.user.uname}</div></div>{/* 评论内容 */}<div className="root-reply"><span className="reply-content">{item.content}</span><div className="reply-info">{/* 评论时间 */}<span className="reply-time">{item.ctime}</span>{/* 评论数量 */}<span className="reply-time">点赞数:{item.like}</span>{/* 删除按钮 */}{/* 判断是否是当前登录用户 */}{item.user.uid===user.uid&&(<span className="delete-btn"onClick={()=>handleDelete(item.rpid)}>删除</span>)}</div></div></div></div>))}</div></div></div>)}exportdefaultApp

问:为什么删除评论是客户端调用过滤评论,而不是请求数据库删除,然后再从数据库获取最新评论列表呢?

这是一个很好的问题!让我来解释一下这两种删除评论的实现方式:

当前代码的实现方式(本地状态管理)

consthandleDelete=(rpid)=>{setCommentList(commentList.filter(item=>item.rpid!==rpid))}

这种方式是客户端状态管理,直接修改本地的状态数据。

两种方式的对比

1.本地过滤方式(当前代码)

优点:

  • 🚀响应速度快- 无需等待网络请求
  • 💰节省服务器资源- 减少API调用次数
  • 🎯用户体验好- 立即反馈,无加载等待

缺点:

  • ⚠️数据不同步- 只是前端展示删除,后端数据库还存在
  • 🔄页面刷新后恢复- 数据会重新从服务器加载

2.API删除方式(你提到的方式)

consthandleDelete=async(rpid)=>{try{// 1. 调用删除APIawaitdeleteCommentAPI(rpid)// 2. 重新获取评论列表constnewList=awaitgetCommentsAPI()setCommentList(newList)}catch(error){console.error('删除失败:',error)}}

优点:

  • 数据真实同步- 前后端数据一致
  • 🔒数据持久化- 删除后数据真正消失

缺点:

  • 🐌响应较慢- 需要等待两次网络请求
  • 💸服务器负担重- 每次操作都需要API调用

实际项目中的最佳实践

在真实项目中,通常会采用混合方式

consthandleDelete=async(rpid)=>{try{// 1. 立即更新UI(乐观更新)setCommentList(commentList.filter(item=>item.rpid!==rpid))// 2. 后台调用删除APIawaitdeleteCommentAPI(rpid)// 3. 如果删除失败,恢复UI状态}catch(error){// 恢复删除的评论setCommentList(originalList)alert('删除失败,请重试')}}

总结

当前代码可能是:

  1. 学习Demo- 专注于React状态管理学习
  2. 原型阶段- 还未连接后端服务
  3. 离线应用- 数据只在本地存储

在实际生产环境中,建议使用乐观更新的方式,既保证用户体验,又确保数据一致性!

http://www.jsqmd.com/news/1219103/

相关文章:

  • aiolimiter核心原理解析:揭秘漏桶算法如何保障asyncio服务稳定性
  • SeasonalInvite 电子贺卡钓鱼滥用 RMM 工具攻击机理与分层防御研究
  • 深度解析SMUDebugTool:AMD Ryzen处理器硬件级调试与性能调优技术指南
  • 从P1265公路修建题解析Prim与Kruskal算法核心差异与选型策略
  • Unity相机拍照与本地保存:RenderTexture方案与跨平台实现详解
  • Python爬取小红书笔记信息加图片(仅供学习参考)
  • TMS320F28003x CLB HLC指令集深度解析与嵌入式实时控制实践
  • 哔哩下载姬终极指南:如何快速免费下载B站8K高清视频
  • 解决 chls.pro/ssl 无法进入问题
  • Kimodo-SOMA-SEED-v1.1 商业应用案例:数字孪生与工业仿真的完整指南
  • 深入理解Llama-3.3-70B-Instruct-w4a16架构:8192隐藏层与64注意力头详解
  • 程序员誓言Programmer‘s Oath:为什么每个开发者都需要道德准则?[特殊字符]
  • 跨境资金跑腿式诈骗全链路风险识别与多层协同拦截机制研究
  • live-app-android社区贡献指南:如何参与开源项目开发与维护
  • Arbiter社区贡献指南:如何参与开源多智能体框架的开发
  • ES6-learning:函数扩展的7个重要特性
  • AI智能客服系统:从FAQ机器人到大模型坐席助手
  • AI智能体开发学习文档(四)
  • KnpGaufretteBundle:Symfony文件系统抽象层终极指南 [特殊字符]
  • Unity HUD GPU加速渲染:自定义管线实现极致性能优化
  • 空洞骑士模组管理器Scarab:3分钟掌握游戏模组安装与管理
  • React Photo Album完全指南:打造响应式照片画廊的终极解决方案
  • ncmdump终极指南:三步解锁网易云加密音乐,重获跨平台播放自由
  • Unity Timeline集成Spine动画:实现2D骨骼动画的精确时序控制
  • 英雄联盟回放播放终极方案:ROFL-Player完整使用指南
  • 5步打造完美黑苹果:国光OpenCore新手终极指南
  • 联想拯救者工具箱完整指南:释放游戏本潜能的终极开源工具
  • C2000 eQEP模块全解析:从正交编码器信号到高精度速度估算
  • 二.双链表
  • 2026年装修建材GEO优化服务商盘点,谁更适配AI搜索获客? - 装企自媒体训练营辉哥