Ant Design中Radio内嵌Dropdown点击触发重渲染无法选值的解决方法
解决Ant Design Radio内嵌Select时下拉无法选择的问题
问题复现代码
import React, { useState } from "react"; import "./index.css"; import type { RadioChangeEvent } from "antd"; import { Radio, Space, Select } from "antd"; const App: React.FC = () => { const [value, setValue] = useState(1); const onChange = (e: RadioChangeEvent) => { console.log("radio checked", e.target.value); setValue(e.target.value); }; return ( <Radio.Group onChange={onChange} value={value}> <Space direction="vertical"> <Radio value={1}>Option A</Radio> <Radio value={2}>Option B</Radio> <Radio value={3}>Option C</Radio> <Radio value={4}> <Select defaultValue="lucy" style={{ width: 120 }} options={[ { value: "jack", label: "Jack" }, { value: "lucy", label: "Lucy" }, { value: "Yiminghe", label: "yiminghe" }, { value: "disabled", label: "Disabled", disabled: true }, ]} onClick={(e) => e.stopPropagation()} /> </Radio> </Space> </Radio.Group> ); }; export default App;
问题原因
点击Select下拉选项时,事件会向上冒泡到外层Radio组件,触发Radio的选中状态变更,进而触发Radio.Group的onChange回调更新value,导致组件重渲染,Select下拉菜单被强制关闭,无法完成选择。
解决方案
以下两种方式均可有效阻止事件冒泡,解决该问题:
方式一:自定义下拉菜单容器拦截事件
通过Select的dropdownRender属性,给下拉菜单外层包裹容器并阻止事件冒泡:
import React, { useState } from "react"; import "./index.css"; import type { RadioChangeEvent } from "antd"; import { Radio, Space, Select } from "antd"; const App: React.FC = () => { const [value, setValue] = useState(1); const onChange = (e: RadioChangeEvent) => { console.log("radio checked", e.target.value); setValue(e.target.value); }; return ( <Radio.Group onChange={onChange} value={value}> <Space direction="vertical"> <Radio value={1}>Option A</Radio> <Radio value={2}>Option B</Radio> <Radio value={3}>Option C</Radio> <Radio value={4}> <Select defaultValue="lucy" style={{ width: 120 }} options={[ { value: "jack", label: "Jack" }, { value: "lucy", label: "Lucy" }, { value: "Yiminghe", label: "yiminghe" }, { value: "disabled", label: "Disabled", disabled: true }, ]} onClick={(e) => e.stopPropagation()} dropdownRender={(menu) => ( <div onClick={(e) => e.stopPropagation()}>{menu}</div> )} /> </Radio> </Space> </Radio.Group> ); }; export default App;
方式二:在Radio点击事件中过滤Select操作
给Radio添加onClick事件,判断点击目标是否属于Select组件,若是则阻止事件传播和默认行为:
import React, { useState } from "react"; import "./index.css"; import type { RadioChangeEvent } from "antd"; import { Radio, Space, Select } from "antd"; const App: React.FC = () => { const [value, setValue] = useState(1); const onChange = (e: RadioChangeEvent) => { console.log("radio checked", e.target.value); setValue(e.target.value); }; return ( <Radio.Group onChange={onChange} value={value}> <Space direction="vertical"> <Radio value={1}>Option A</Radio> <Radio value={2}>Option B</Radio> <Radio value={3}>Option C</Radio> <Radio value={4} onClick={(e) => { const isSelectElement = e.target.closest(".ant-select") !== null; if (isSelectElement) { e.stopPropagation(); e.preventDefault(); } }} > <Select defaultValue="lucy" style={{ width: 120 }} options={[ { value: "jack", label: "Jack" }, { value: "lucy", label: "Lucy" }, { value: "Yiminghe", label: "yiminghe" }, { value: "disabled", label: "Disabled", disabled: true }, ]} /> </Radio> </Space> </Radio.Group> ); }; export default App;
说明
- 方式一针对下拉菜单事件单独拦截,保留了Radio正常点击选中的功能;
- 方式二直接过滤Radio的误触发场景,逻辑更直观,适合不需要通过点击Select区域选中Radio的场景。
内容的提问来源于stack exchange,提问作者Cường Nguyễn Đức
相关产品推荐
相关产品推荐

