React中复选框与单选按钮组件的代码复用方案问询
你的思路完全没问题!把这两个组件合并成一个可配置的FormControlGroup绝对是减少重复代码的最佳实践之一。下面我给你详细拆解具体怎么实现:
1. 定义核心可复用组件
首先创建FormControlGroup组件,通过一个type属性来决定渲染复选框还是单选按钮,值可以是'checkbox'或'radio'。同时把两个组件共有的逻辑(比如遍历选项、处理选中状态、onChange事件)都抽离到这个组件里:
import React from 'react'; const FormControlGroup = ({ type = 'checkbox', // 默认渲染复选框,可选值为'radio' options, // 选项数组,格式建议为 [{ label: '选项文本', value: '选项值' }, ...] selectedValues, // 选中的值:复选框用数组,单选用单个值(字符串/数字) onChange, // 状态变更回调函数 name, // 表单控件的name属性,单选按钮必须设置统一name才能实现互斥 className = '', // 自定义外层容器类名,增强灵活性 }) => { // 统一处理单选/复选框的变更逻辑 const handleChange = (event) => { const { value, checked } = event.target; if (type === 'radio') { onChange(value); } else { // 复选框:更新选中值数组 const newSelected = checked ? [...selectedValues, value] : selectedValues.filter(val => val !== value); onChange(newSelected); } }; return ( <div className={`form-control-group ${className}`}> {options.map((option) => { // 判断当前选项是否被选中 const isChecked = type === 'radio' ? selectedValues === option.value : selectedValues.includes(option.value); return ( <label key={option.value} className="control-label"> <input type={type} name={name} value={option.value} checked={isChecked} onChange={handleChange} disabled={option.disabled} // 支持单个选项禁用 /> {option.label} </label> ); })} </div> ); }; export default FormControlGroup;
2. 组件使用示例
现在你可以用这个单一组件快速实现复选框组和单选按钮组:
复选框组用法
import FormControlGroup from './FormControlGroup'; const FavoriteFruits = () => { const [selectedFruits, setSelectedFruits] = React.useState(['apple']); return ( <div> <h3>选择你喜欢的水果</h3> <FormControlGroup type="checkbox" options={[ { label: '苹果', value: 'apple' }, { label: '香蕉', value: 'banana' }, { label: '橙子', value: 'orange', disabled: true }, // 可选禁用单个选项 ]} selectedValues={selectedFruits} onChange={setSelectedFruits} className="fruit-group" /> </div> ); };
单选按钮组用法
import FormControlGroup from './FormControlGroup'; const GenderSelector = () => { const [selectedGender, setSelectedGender] = React.useState('male'); return ( <div> <h3>选择你的性别</h3> <FormControlGroup type="radio" name="gender" // 单选必须设置统一name,确保互斥 options={[ { label: '男', value: 'male' }, { label: '女', value: 'female' }, { label: '其他', value: 'other' }, ]} selectedValues={selectedGender} onChange={setSelectedGender} /> </div> ); };
3. 额外优化建议
- 类型校验:可以用PropTypes或者TypeScript约束props的类型,避免错误使用。比如用TypeScript定义
FormControlGroupProps接口,明确type的可选值、options的结构等。 - 自定义渲染:如果需要更复杂的选项布局,可以新增
renderOption属性,允许传入自定义渲染函数,让组件更灵活:// 组件内修改渲染逻辑 {options.map((option) => ( <div key={option.value}> {renderOption ? renderOption(option, { isChecked, handleChange }) : ( // 默认渲染逻辑 <label className="control-label"> <input {...inputProps} /> {option.label} </label> )} </div> ))} - 状态默认值:可以在组件内部给
selectedValues设置默认值(比如复选框默认空数组,单选默认空字符串),避免外部不传值时出错。
内容的提问来源于stack exchange,提问作者GuerillaRadio
相关产品推荐
相关产品推荐

