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

React评论功能提交按钮单次点击触发两次回调问题求助

问题根因

你遇到的回调执行两次问题核心是重复绑定了点击事件监听器,具体原因如下:

  • 你没有用React自带的onClick属性绑定事件,而是用原生addEventListener手动给#confirm按钮绑定监听,且每次getComments执行时都会新增一个监听器,旧的监听器没有被清理,点一次按钮就会触发所有绑定过的回调。
  • 你的useEffect依赖项是prev,每次点击回复修改prev都会重新触发getComments,监听器就会多绑一次,你现在触发两次说明已经绑了2个监听器,后续如果继续操作还会触发更多次。
  • 你写的clicked状态拦截完全无效:每个监听器的回调都是独立闭包,拿到的clicked是绑定时的旧值,不是最新的提交状态,自然拦不住重复执行。

修复方案

优先方案(推荐)

完全去掉所有手动绑定事件的逻辑,改用React标准的事件绑定方式:

  1. 把提交评论的逻辑单独抽成一个公共异步函数,避免ifNoCom和ifCom里重复写冗余代码
  2. 直接在你返回的Confirm组件上添加onClick属性绑定这个抽离好的提交函数:
// 抽离提交逻辑
const submitComment = async () => {
  if(clicked) return cogoToast.warn("Already commenting...")
  setClicked(true)
  try {
    const content = document.querySelector("#commentcontent").value
    const {data} = await axios({
      url: vars.BACKENDURL + "/comment",
      withCredentials: true,
      method: "POST",
      data: {
        article: article,
        comment: {
          content: content,
          prevId: prev === "" ? null : prev,
        },
      },
    })
    if(typeof data != "object") {
      return cogoToast.error("Please sign in first!")
    }
    setPrev("")
    // 提交成功后重新拉取评论列表更新视图
    getComments()
  } catch (err) {
    console.error(err)
  } finally {
    setClicked(false)
  }
}

// 组件里绑定事件
<Confirm id="confirm" onClick={submitComment}>Post</Confirm>
  1. 删掉ifNoCom和ifCom里所有setTimeout加addEventListener的相关代码,完全不需要手动绑定。

如果你非要保留原生绑定的写法

必须在绑定新的监听器前移除旧的,或者在useEffect的清理函数里统一移除:

  • 首先把回调函数定义成外部可引用的变量,不能写匿名函数,否则removeEventListener找不到要移除的回调
  • 每次绑定前先调用removeEventListener移除上一次的回调
  • 或者在useEffect的返回函数里统一清理所有监听器

其他可优化点

  • 不要用forEach加await遍历异步请求,forEach不支持异步等待,你写的await article.commentsArr.forEach完全无效,建议改成for...of循环或者Promise.all批量处理请求
  • 你写的!comments.includes({ ...data })判断永远为真,对象是引用类型,两个结构一样的对象也不会被includes判定为相等,这段判断没有任何作用
  • 尽量不要用document.querySelector拿DOM元素的value,评论输入框可以用受控组件,直接用useState存输入内容,更符合React的写法

内容的提问来源于stack exchange,提问作者ReginaTheMean

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 22:06:03