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

React中td点击事件e.target.id偶尔为空的问题求助

问题:React中<td>的onClick事件偶尔无法获取id值

在React项目里,给绑定了onClick事件的<td>元素设置了id(该id来自Axios.get请求后的数据映射渲染),点击时要把id传给Node.js后端执行删除操作,但偶尔会出现e.target.id为空的情况——明明<td>本身是有id的,试过用Promise处理但问题依旧。相关代码如下:

<td
  className="deletebutton"
  id={list.id}
  onClick={async (e) => {
    const deleteid = await e.target.id;
    const socket = io(`http://${process.env.REACT_APP_RUN}:3001`, {
      transports: ["websocket", "polling", "flashsocket"]
    });

    await axios.post(
      `http://${process.env.REACT_APP_RUN}:3001/api/delete/single`,
      {
        idDelete: "" + deleteid + ""
      }
    );
    await socket.emit("get date", ip);
  }}
>
  delete
  <i>
    <IconContext.Provider value={{ size: "16px", className: "factor-icons" }}>
      <div>
        <AiFillDelete />
      </div>
    </IconContext.Provider>
  </i>
</td>

问题原因

这是事件冒泡+事件目标指向导致的问题:当你点击<td>内部的子元素(比如<i>、<div>或者图标组件AiFillDelete)时,e.target会指向被点击的那个子元素,而这些子元素并没有设置id,所以拿到的自然是空值;只有直接点击<td>的空白区域时,e.target才会指向<td>,才能正确拿到id。


解决方法

方法1:用e.currentTarget替代e.target

e.currentTarget永远指向绑定了当前事件处理函数的元素(也就是这里的<td>),不管你点击的是它内部的哪个子元素,都能稳定拿到<td>的id。同时注意去掉没必要的await——e.target.id不是异步操作,socket.emit也不返回Promise,不需要等待:

<td
  className="deletebutton"
  id={list.id}
  onClick={async (e) => {
    const deleteid = e.currentTarget.id;
    const socket = io(`http://${process.env.REACT_APP_RUN}:3001`, {
      transports: ["websocket", "polling", "flashsocket"]
    });

    await axios.post(
      `http://${process.env.REACT_APP_RUN}:3001/api/delete/single`,
      {
        idDelete: deleteid
      }
    );
    socket.emit("get date", ip);
  }}
>
  {/* 内部元素不变 */}
</td>

方法2:直接使用渲染时的list.id

既然渲染<td>的时候已经有list.id这个值,完全可以直接在事件处理函数里用它,彻底绕开事件对象的问题,这是最可靠的方式:

<td
  className="deletebutton"
  id={list.id}
  onClick={async () => {
    const deleteid = list.id;
    const socket = io(`http://${process.env.REACT_APP_RUN}:3001`, {
      transports: ["websocket", "polling", "flashsocket"]
    });

    await axios.post(
      `http://${process.env.REACT_APP_RUN}:3001/api/delete/single`,
      {
        idDelete: deleteid
      }
    );
    socket.emit("get date", ip);
  }}
>
  {/* 内部元素不变 */}
</td>

方法3:CSS禁用子元素的点击事件

如果<td>内部的子元素不需要单独处理点击事件,可以给它们加pointer-events: none样式,让点击事件直接穿透到<td>:

.deletebutton > * {
  pointer-events: none;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:43:14