I have 2 hidden customized radio button components, when we click on the label the radio is checked.
I have added a functionality that when the radio is checked there’s a styling effect that appears on the label (a border with padding and background). The issue here is that when I click on the other radio label, the same styling is duplicated even though there’s only one radio button that is checked. Here’s the parent component :
<div className="flex lg:justify-center gap-2 lg:gap-6">
<EspaceCard
value="miami"
onChange={(e) =>
setValues((prev) => ({ ...prev, espace: e.target.value }))
}
checked={values.espace === 'miami'}
text="MIAMI ROOM"
/>
<EspaceCard
onChange={(e) =>
setValues((prev) => ({ ...prev, espace: e.target.value }))
}
value="jungle"
checked={values.espace === 'jungle'}
text="JUNGLE ROOM"
/>
</div>
Here’s the individual radio button component: (EspaceCard)
'use client'
import { ChangeEvent, useState } from 'react';
interface InputProps {
text: string;
value: string;
checked?: boolean;
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
}
const EspaceCard = ({ text, value, onChange, checked }: InputProps) => {
const [clicked, setClicked] = useState(checked);
return (
<>
<label
htmlFor={text}
onClick={() => setClicked(!clicked)}
className={`p-4 rounded-lg ${
clicked ? 'border-gold border bg-light-gold' : ''
}`}
>
<div className="box-border lg:w-52 text-center relative bg-black px-6 py-6 h-60 rounded-xl shadow-lg lg:hover:scale-110 transition-all cursor-pointer border-gold border-4 before:content-[''] before:absolute before:top-0 before:left-1/2 before:bg-gold before:h-2 before:rounded-b-full before:w-1/2 before:-translate-x-1/2 grid place-content-center">
<p className="text-xl lg:text-2xl font-bold text-gold">{text}</p>
</div>
</label>
<input
type="radio"
id={text}
name="espace"
value={value}
onChange={onChange}
checked={checked}
hidden
/>
</>
);
};
export default EspaceCard;
>Solution :
Here to the local state clicked on your EspaceCard component. The state is managed independently for each instance of the component, so when you click on one radio label, the clicked state is updated for that specific instance, but not for the other instance.
just remove the local state clicked from EspaceCard component and manage the checked state through the checked prop
<label
htmlFor={text}
className={`p-4 rounded-lg ${
checked ? "border-gold border bg-light-gold" : ""
}`}
onClick={() => handleLabelClicked()}
>....</label>
where handleLabelClicked is a function that updates the checked value in the parent component so you have to pass this function as well to EspaceCard as props:
const EspaceCard = ({ text, value, onChange, checked, handleLabelClicked }: InputProps) => {
//...
}