React点赞按钮状态更新异常:首次点击状态为undefined
评论点赞组件状态异常问题
我开发的评论点赞/取消点赞组件,初始运行时状态无法维持。首次点击时状态为undefined,但第二次点击点赞按钮后状态能正常更新。
相关代码
JSX 代码
<div className="flex justify-between gap-5" onL> <h4 className="text-text font-medium text-base"> {comment?.userID?.name} </h4> <Button className="flex-shrink-0 flex-grow-0" onClick={() => { setHasLiked((prevHasLiked) => { return { ...prevHasLiked, [comment?.userID?._id]: !prevHasLiked[comment?.userID?._id], }; }); onSubmmitLikeComment( comment?._id, comment?.userID?._id ); }} > {hasLiked[comment?.userID._id] ? ( <Empheart stroke="red" fill="red" /> ) : ( <Empheart stroke="black" fill="black" /> )} {comment?.like_count} </Button> </div>
onSubmmitLikeComment 函数
const onSubmmitLikeComment = async (commentID, userID) => { console.log("userID", userID); // 能正确获取userID const userHasLiked = hasLiked[userID]; // 首次点击时返回undefined,第二次点击后状态正常更新 console.log("userHasLiked", userHasLiked); console.log("hasLiked", hasLiked); try { const response = await fetch("/api/likeComment", { method: "POST", headers: { "Content-Type": "application/json", "X-App-Type": "WEB_APP", }, body: JSON.stringify({ commentID, userID, hasLiked: userHasLiked }), }); const result = await response.json(); console.log("result", result); if (result.isSuccess) { setComments((prevComments) => prevComments.map((comment) => comment?._id == commentID && comment?.userID?._id === userID ? { ...comment, like_count: userHasLiked ? comment.like_count - 1 : comment.like_count + 1, } : comment ) ); setHasLiked((prev) => ({ ...prev, [userID]: !userHasLiked, })); } } catch (error) { console.error("Unable to update like/unlike comment ", error); alert( "An error occurred while liking/disliking comment. Please try again." ); } };
状态定义
const [comments, setComments] = useState([]); const [hasLiked, setHasLiked] = useState({});
问题原因
- React状态更新的异步性:
setHasLiked是异步操作,点击按钮时先调用setHasLiked,紧接着执行onSubmmitLikeComment,此时hasLiked还没完成更新,首次点击时取到的是空对象里的undefined。 - 重复更新状态:点击事件里手动更新了一次
hasLiked,接口成功后又再次更新,导致状态逻辑混乱,前端UI和接口传递的状态不一致。
解决方案
1. 简化点击事件逻辑
去掉点击事件中直接调用的setHasLiked,改为统一在接口回调里处理状态:
<Button className="flex-shrink-0 flex-grow-0" onClick={() => { onSubmmitLikeComment(comment?._id, comment?.userID?._id); }} > {hasLiked[comment?.userID._id] ? ( <Empheart stroke="red" fill="red" /> ) : ( <Empheart stroke="black" fill="black" /> )} {comment?.like_count} </Button>
2. 优化onSubmmitLikeComment函数
处理undefined的默认值,确保状态获取准确:
const onSubmmitLikeComment = async (commentID, userID) => { console.log("userID", userID); // 处理undefined情况,默认未点赞 const currentHasLiked = hasLiked[userID] ?? false; console.log("userHasLiked", currentHasLiked); try { const response = await fetch("/api/likeComment", { method: "POST", headers: { "Content-Type": "application/json", "X-App-Type": "WEB_APP", }, body: JSON.stringify({ commentID, userID, hasLiked: currentHasLiked }), }); const result = await response.json(); console.log("result", result); if (result.isSuccess) { // 更新评论点赞数 setComments((prevComments) => prevComments.map((comment) => comment?._id === commentID ? { ...comment, like_count: currentHasLiked ? comment.like_count - 1 : comment.like_count + 1, } : comment ) ); // 更新点赞状态 setHasLiked((prev) => ({ ...prev, [userID]: !currentHasLiked, })); } } catch (error) { console.error("无法更新评论点赞状态 ", error); alert( "点赞/取消点赞时发生错误,请重试。" ); } };
3. 额外优化建议
- 初始化
hasLiked时,可根据接口返回的评论数据,提前标记已点赞的用户ID,避免初始状态为空导致的undefined问题。 - 给按钮添加加载状态,防止用户重复点击触发多次请求。
内容的提问来源于stack exchange,提问作者Hannan Yusuf Khan
相关产品推荐
相关产品推荐

