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

React受控自定义单选按钮无法重新选中的问题解决

解决React受控单选按钮重复选中不触发onChange的问题

问题原因

原生HTML的<input type="radio">仅在从未选中切换为选中状态时触发onChange事件;若按钮已处于选中状态,再次点击不会触发该事件。你的自定义组件依赖原生radio的onChange,因此无法响应重复选中的操作。

解决方案

给自定义单选按钮的交互区域(外层label或视觉化容器)添加onClick事件,当按钮已选中且未禁用时,手动调用传入的onChange方法。同时需要补全受控组件的核心绑定逻辑。

修改后的Radio组件代码

import { FC, useId } from 'react';
import clsx from 'clsx';

interface RadioProps {
  label: string;
  checked: boolean;
  onChange: () => void;
  disabled?: boolean;
}

export const Radio: FC<RadioProps> = ({
  label,
  checked,
  onChange,
  disabled = false,
}) => {
  const id = useId();

  const handleLabelClick = () => {
    if (!disabled && checked) {
      // 已选中状态下手动触发onChange
      onChange();
    }
  };

  return (
    <div>
      <label
        htmlFor={id}
        className={clsx(
          disabled ? 'cursor-not-allowed' : 'cursor-pointer',
          'inline-flex items-center mr-4'
        )}
        onClick={handleLabelClick}
      >
        <input
          onChange={onChange}
          type="radio"
          disabled={disabled}
          id={id}
          className="hidden"
          checked={checked} // 受控组件必须绑定checked,保证状态同步
        />
        <div
          className={clsx(
            checked ? 'after:scale-1' : 'after:scale-0',
            'radio__radio w-5 h-5 border-2 border-gray-400 rounded-full mr-2 box-border p-0.5',
            "after:content-[''] after:block after:h-full after:w-full after:bg-green-500 after:rounded-full after:transform after:transition-transform after:duration-[35ms]"
          )}
        />
        {label}
      </label>
    </div>
  );
};

关键修改点

  • 补全checked绑定:受控组件必须给原生radio绑定checked属性,确保组件状态与原生元素状态完全同步,这是你原代码中缺失的核心逻辑。
  • 添加点击事件处理:在label上绑定onClick事件,当按钮已选中且未禁用时,手动调用onChange,实现重复选中触发回调的需求。
  • 禁用状态判断:点击事件中先校验禁用状态,避免无效操作。

调用方式无需修改

你的原有渲染代码可以保持不变:

<div>
  {items.map(({ label, id }) => {
    return (
      <Radio
        key={id}
        label={label}
        checked={id === selected}
        onChange={() => onSelect(id)}
      />
    );
  })}
</div>

修改后,无论是切换未选中选项,还是重复点击已选中选项,都会触发onChange回调,满足需求。

内容的提问来源于stack exchange,提问作者sir-haver

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:55:15