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
相关产品推荐
相关产品推荐

