0
const [checked, checkedState] =useState(null)
 const handleClick = () =>{
    checkedState(false)
  }

 <div className='radiobtn'>
          <input type="radio" value={5} name="discount" checked={checked} id="five" />
          <label htmlFor="five">5%</label>
          </div>
          <div className='radiobtn'>
          <input type="radio" value={10} name="discount" checked={checked} id="ten"/>
          <label htmlFor="ten">10%</label>
            </div>
            <div className='radiobtn'>
            <input type="radio" value={15} name="discount" checked={checked} id="fifteen"/>
            <label htmlFor="fifteen">15%</label>
            </div>
            <div className='radiobtn'>
            <input type="radio" value={25} name="discount" checked={checked} id="twentyfive"/>
            <label htmlFor="twentyfive" >25%</label>
            </div>
            <div className='radiobtn'>
            <input type="radio" value={50} name="discount" checked={checked} id="fifty" />
            <label htmlFor="fifty">50%</label>
</div>

<button onClick={()=>handleClick()}>reset</button>

i used the useState to uncheck all the radio button but then the radio button dont chnage at all when clicked again because they are all false. Am i forgetting something ? I tried using null value in useState but it give Warning: A component is changing an uncontrolled input to be controlled.

  • 1
    save the value in state instead of `checked` boolean. and then in component do this change `checked={state === 25}`, `checked={state === 15}` etc. Also add onChange handler to your checkboxes – boop_the_snoot Aug 29 '22 at 05:50

2 Answers2

1

Simplified example using useCallback

const { useCallback } = require("react");

const [checked, checkedState] = useState(null);

const getRadioProps = useCallback((id, value) => {
  return {
    id,
    value,
    type: "radio",
    name: "discount",
    checked: checked === value, // this will toggle the checked state
    onChange: () => checkedState(value),
  };
}, [checked]); // update the props for all checkboxes, if the checked value changes

<>
  <div className="radiobtn">
    <input {...getRadioProps("five", 5)} />
    <label htmlFor="five">5%</label>
  </div>
  <div className="radiobtn">
    <input {...getRadioProps("ten", 10)} />
    <label htmlFor="ten">10%</label>
  </div>
  <div className="radiobtn">
    <input {...getRadioProps("fifteen", 15)} />
    <label htmlFor="fifteen">15%</label>
  </div>

  <button onClick={() => checkedState(null)}>reset</button>
</>;

Here we are storing the value of the radio button, instead of true or false

boop_the_snoot
  • 3,209
  • 4
  • 33
  • 44
  • Bro it worked like a charm, plz tell me on how you tackled this problem i was pulling my hair out on this one. Could you help me understand this code ```checked: checked === value```, So basically we trying to find whether the radio button i clicked equals to the radio button UI ? – Suleman Mughal Aug 29 '22 at 16:41
  • 1
    there are two parts to your problem. First, saving the correct state (only once, not for every radio button). Second, toggling the checked state based on the previously saved state. So, the `onChange` handler will update the state of the RadioGroup and save the value of current radio button. Once it is updated by React, `getRadioProps` will re-trigger again, where `checked: checked === value` will check whether the radio button should be in checked state or not, and that is evaluated based on which radio button was clicked. That's why we have added this callback to every radio button – boop_the_snoot Aug 29 '22 at 17:02
  • 1
    Also remember, if you bind `value={someVariable}` for any form control, it becomes a must to attach a `onChange` handler to the same control. This is called a controlled-component – boop_the_snoot Aug 29 '22 at 17:06
0

Yes, so it's a bit confusing. You should use a form library like Formik or react-hook-form to more properly/easily manage your form states. However, the error you are getting Warning: A component is changing an uncontrolled input to be controlled. is because the input control in react/html has its own ability to control its "checked" state. So once you update the state programmtically, using setChecked(false), you are now controlling the state outside of the default control that is natively baked into that component.

So, you should use those form libs. Or you should bind to the click event on each <input onClick="prev => setChecked(!prev)">. However, this will change all input states at the same time from then on since they are all using the same useState value.

If you didn't want to use a form library like I said above, you would simply have to create a useState with an object of all the input values (not advised)

const [checked, setChecked] = useState({
  input1: false,
  input2: true,
  input3: false,
  ...
}),

or create a separate useState for each input element. As in

const [input1, setInput1] =useState(null)
const [input2, setInput2] =useState(null)
const [input3, setInput3] =useState(null)
...

You could also use a useReducer hook which would be better than the latter two options but worse than a form lib

DOZBORNE
  • 560
  • 3
  • 13