React中如何正确分组单选按钮?自定义组件单选逻辑疑问
name也能实现单选按钮分组? 你说的没错,原生HTML里单选按钮确实是靠相同的name属性实现分组,同一组内只能选一个。但这段代码走了另一条路:用React的受控组件机制完全接管了单选按钮的选中状态,不需要依赖浏览器原生的name分组逻辑。
具体拆解代码的工作流程:
RadioGroup组件的核心作用
RadioGroup接收两个关键属性:selected(当前选中的单选值)和onChange(选中值变化时的回调)。它会遍历所有子RadioOption组件,通过React.cloneElement给每个子组件注入两个属性:- 统一的
onChange回调 - 计算好的
checked状态:只有当子组件的value等于selected时,checked才为true,其他都是false
- 统一的
RadioOption的受控逻辑
每个RadioOption里的<input type="radio">,它的checked状态不是由浏览器自主管理,而是完全由父组件传过来的checked属性控制。当用户点击这个单选按钮时,会触发onChange,把当前按钮的value传给上层RadioGroup的onChange,进而更新外部的selected状态。实现单选的关键
当外部的selected状态更新后,RadioGroup会重新渲染所有子RadioOption,此时只有value和selected匹配的那个单选按钮会被设为checked={true},其他都会变成checked={false}——这就强制实现了同一时间只能选中一个的效果。
补充:代码的小缺陷
这段代码虽然功能正常,但从语义化和降级体验来说有个小问题:每个单选按钮的name设成了value(也就是每个按钮的name都不一样),这会导致浏览器原生的单选分组失效。如果用户禁用了JavaScript,这些单选按钮就可以同时选中了。更规范的写法应该是给RadioGroup加一个name属性,传递给所有子RadioOption的input,这样既能用React受控逻辑,也能保留原生行为的兜底。
内容的提问来源于stack exchange,提问作者Anthony

