You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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({});

问题原因

  1. React状态更新的异步性:setHasLiked是异步操作,点击按钮时先调用setHasLiked,紧接着执行onSubmmitLikeComment,此时hasLiked还没完成更新,首次点击时取到的是空对象里的undefined。
  2. 重复更新状态:点击事件里手动更新了一次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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 15:07:35