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

React中内嵌input的label标签为何会触发两次onClick事件?

为何内部包含input的label标签会使onClick事件执行两次?

这事儿是HTML原生行为加事件冒泡搞出来的:

  • 当你点击label里的radio按钮时,浏览器先触发input的点击事件,接着因为label和input的关联特性,浏览器会自动触发一次label的点击事件,用来实现“点label也能选中控件”的功能。
  • 同时,input的点击事件会向上冒泡到它的父元素label,又触发了一次label的onClick回调。
  • 再加上React 18的StrictMode在开发环境下会重复执行事件回调来检测问题,这就让两次触发的现象更显眼,但就算去掉StrictMode,原生行为导致的两次触发依然存在。

解决办法

有几种方式可以搞定:

  • 阻止事件冒泡:给input加onClick事件,阻止事件向上传递,这样就不会因为冒泡再触发一次label的回调:
function App() {
  return (
    <label className="label" onClick={()=> console.log("label onClick")}>
      <input 
        className="radio" 
        type="radio" 
        onClick={(e) => e.stopPropagation()} 
      />
    </label>
  );
}
  • 分开label和input:不用嵌套结构,改用label的htmlFor属性和input的id关联,这样点击label时只会触发一次回调:
function App() {
  return (
    <>
      <label 
        className="label" 
        htmlFor="radio-btn"
        onClick={()=> console.log("label onClick")}
      ></label>
      <input 
        id="radio-btn"
        className="radio" 
        type="radio" 
      />
    </>
  );
}
  • 换绑定位置:如果没必要在label上绑定事件,直接把逻辑绑在input的onClick上就行。

原代码示例

JS代码

const { StrictMode } = React;
const { createRoot } = ReactDOM;

function App() {
  return (
    <label className="label" onClick={()=> console.log("label onClick")}>
      <input className="radio" type="radio" />
    </label>
  );
}

const root = createRoot(document.getElementById("root"));
root.render(<StrictMode><App /></StrictMode>);

CSS代码

.label {
  display: block;
  background-color: red;
  width: 300px;
  height: 100px;
  position: relative;
}

.radio {
  width: 30px;
  height: 30px;
}

HTML代码

<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:56:15