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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:36:04