React嵌套评论对象编辑问题:解决子评论触发父评论信息异常
React 嵌套评论编辑功能实现方案
场景说明
现有嵌套结构的评论状态数据(包含父评论及子回复),已实现可正确删除任意层级评论的功能,但复用该递归逻辑编写评论编辑功能时遇到问题:点击id为4的子评论,会错误获取到父评论(id=2)的信息,无法定位到目标子评论进行编辑。需求是点击编辑按钮后,将对应评论内容替换为填充原有内容的textarea,编辑完成后保存并更新comments状态。
已有可正常工作的删除功能代码
const { comments, setLoading } = useContext(CommentsContext); function handleDelete(e) { setLoading(true); function deleteComment(id, arr) { arr.forEach(function (item, index) { if (item.id == id) { arr.splice(index, 1); } else if (item.replies && item.replies.length > 0) { deleteComment(id, item.replies); } }); } deleteComment(e.target.id, comments); setTimeout(() => { setLoading(false); }, 100); }
解决编辑问题的可行代码
const { comments, setLoading, setComments } = useContext(CommentsContext); function handleEdit(e) { setLoading(true); // 创建状态副本,避免直接修改原状态 const updatedComments = JSON.parse(JSON.stringify(comments)); function editComment(id, arr) { arr.forEach(function (item) { if (item.id === id) { // 替换为带原有内容的textarea item.content = ( <textarea className="w-full h-[100px] bg-secondary border rounded p-3 outline-none" placeholder="Edit a comment..." defaultValue={item.content} /> ); } else if (item.replies && item.replies.length > 0) { // 遍历当前评论的回复列表,精准查找目标子评论 for (let reply of item.replies) { if (reply.id === id) { reply.content = ( <textarea className="w-full h-[100px] bg-secondary border rounded p-3 outline-none" placeholder="Edit a comment..." defaultValue={reply.content} /> ); return; // 找到目标后终止遍历 } // 支持更深层级嵌套回复的编辑(若有需求) if (reply.replies && reply.replies.length > 0) { editComment(id, reply.replies); } } } }); } editComment(e.target.id, updatedComments); // 更新状态触发组件重渲染 setComments(updatedComments); setTimeout(() => { setLoading(false); }, 100); }
关键修复点
- 遵循React状态更新规范:通过深拷贝创建状态副本,避免直接修改原数组导致的状态更新异常
- 精准定位目标评论:遍历父评论的
replies列表直接匹配目标id,解决了之前错误传递父评论id导致的定位偏差问题 - 优化编辑体验:给textarea添加
defaultValue属性,自动填充评论原有内容 - 提升性能:找到目标评论后立即终止遍历,减少不必要的循环操作
内容的提问来源于stack exchange,提问作者Ninety9Balloons
相关产品推荐
相关产品推荐

