I created a simple React custom controlled radio button:
export const Radio: FC<RadioProps> = ({
label,
checked,
onChange,
disabled,
}) => {
const id = useId();
return (
<div>
<label
htmlFor={id}
className={clsx(
disabled ? 'cursor-not-allowed' : 'cursor-pointer',
'inline-flex items-center mr-4'
)}
>
<input
onChange={onChange} // This will be used to check the radio button
type="radio"
disabled={disabled}
id={id}
className="hidden"
/>
<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>
);
};
Now I’m rendering a group of those radio buttons:
<div>
{items.map(({ label, id }) => {
return (
<Radio
key={id}
label={label}
checked={id === selected}
onChange={() => onSelect(id)}
/>
);
})}
</div>
The problem: the onChange of each radio button (inside the input) will only trigger once, so you cannot reselect a radio button. You can switch between them but without the option to re-select, since the onChange in each of them will only fire once. How can I have my Radio component be able to trigger the onChange when re-selecting the radio button?
>Solution :
You need to have both onChange and checked property on the HTML input element. So you have to still pass checked into your <input /> element like so:
const MyCheckableItem = ({ checked, onChange }) => {
return <input checked={checked} onChange={onChange} />
}
For more info, see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#checked