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

为何event.currentTarget有时返回null?React按钮点击场景排查

问题与解决方案解析

问题背景

我在按钮中嵌套SVG图标组件,每个按钮绑定onClick处理器,试图通过事件对象获取按钮的name属性来更新状态。但遇到偶发现象:

  • event.currentTarget有时会返回null
  • 正常情况console.log输出空按钮标签,失效时输出带SVG子元素的按钮,但两种场景下event.currentTarget.name都能即时正确打印,只是后续访问currentTarget时变为null
  • 已找到修复方式:提前把event.currentTarget.name存入常量即可解决,但不清楚原理

核心原因:React事件池的复用机制

React为了优化性能,会维护一个事件对象池:

  • 事件触发时,React从池中取出一个事件对象,填充好属性(比如currentTarget、target等)传给事件处理函数
  • 当事件处理函数执行完毕后,React会立即清空这个事件对象的所有属性(包括currentTarget),并把它放回事件池,供后续事件复用

你的原代码中,raiseState(() => event.currentTarget.name)是把一个回调函数传给状态更新方法,这个回调是异步执行的(React会批量处理状态更新,回调会在事件处理函数完全执行完之后才触发)。等到这个回调执行时,事件对象已经被React回收清空,currentTarget自然变成了null。

而提前把event.currentTarget.name存入常量,相当于在事件对象被回收前,就把name的值提取并保存到了独立变量中,后续异步回调访问的是这个保存的常量,不受事件池回收的影响。

另外你看到console.log即时输出event.currentTarget.name正常,是因为这行代码是同步执行的,此时事件对象还没被回收,属性都处于可用状态。

可靠获取按钮name属性的几种方案

1. 提前存储属性值(你用到的方案)

在事件对象被回收前,把需要的属性值提取出来:

function changeModeHandler(event) {
  const name = event.currentTarget.name;
  console.log(event.currentTarget, name);
  raiseState(() => name);
}

2. 直接传递name参数(更直观)

不用依赖事件对象,绑定事件时直接把按钮的name作为参数传入处理器:

function changeModeHandler(name) {
  raiseState(() => name);
}

return (
  <>
    <button
      onClick={() => changeModeHandler("explain")}
      className=""
      type="button"
      name="explain"
    >
      <BookOpenIcon className="mode-icon" />
    </button>
    <button
      onClick={() => changeModeHandler("summary")}
      className=""
      type="button"
      name="summary"
    >
      <KeyIcon className="mode-icon" />
    </button>
    <button
      onClick={() => changeModeHandler("example")}
      className=""
      type="button"
      name="example"
    >
      <ListBulletIcon className="mode-icon" />
    </button>
  </>

3. 用event.target向上查找按钮(不推荐)

如果一定要基于事件对象,可通过closest方法从触发事件的子元素向上找到父按钮,但这种方法在按钮嵌套多层元素时容易出问题:

function changeModeHandler(event) {
  const button = event.target.closest('button');
  const name = button?.name;
  raiseState(() => name);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 19:10:33