asif kaif
asif kaif

Reputation: 159

React hook form set Value not working for Radio Buttons

On Button Click I want set the value as male or female

Child Components

const NewRad = (props) => {
  const {...rest } = props
  const { control , setValue} = useFormContext()
  const onButtonClick =()=>setValue('salaried', 'yes')
  return (    
    <Controller control={control} name='salaried'
      render={({ field: { value, onChange}, fieldState: { error }}) => {
        return (<FormControl  {...rest}>
            <FormLabel id="demo-error-radios"> Gender</FormLabel>
              <RadioGroup>
               <FormControlLabel value='male' control={<Radio />} label='Male' />
               <FormControlLabel value='female' control={<Radio />} label='Female' />             
              </RadioGroup>                                    
            </FormControl>)}} /> )
}
export default NewRad

Upvotes: 2

Views: 4113

Answers (2)

Max Ma
Max Ma

Reputation: 1130

The given value needs to be a string, even with valueAsNumber

e.g. setValue(String(value)) or <input type={radio} value={String(value)} .../>

And the below 2 steps are not required @7.33 and above,

  1. methods.setValue after mounting
  2. Specify Default value

Upvotes: 0

takanuva15
takanuva15

Reputation: 1688

Ok after some debugging, I checked the browser console logs and I found it was showing me this error:

Material-UI: A component is changing the uncontrolled value state of RadioGroup to be controlled.
Elements should not switch from uncontrolled to controlled (or vice versa).
Decide between using a controlled or uncontrolled RadioGroup element for the lifetime of the component.
The nature of the state is determined during the first render, it's considered controlled if the value is not `undefined`.

To fix it, I set the defaultValue for my radio group name to "null" so that it wasn't undefined:

MyForm.tsx

export default function MyForm() {
  const methods = useForm<any>({ defaultValues: { myRadioGroupName: null } });
    
  useEffect(() => {
    methods.setValue('myRadioGroupName', 'no');
  }, []);
    
  return (
    <FormProvider {...methods}>
      <Box display="flex" p={3}>
        <MyRadioGroup />
      </Box>
    </FormProvider>
  );
}

MyRadioGroup.tsx

export default function MyRadioGroup() {
  const { control, register } = useFormContext();
  const myRadioGroupValue = useWatch({ control, name: 'myRadioGroupName' });

  return (
    <Box display="flex" flexDirection="column" style={{ gap: '1rem' }}>
      <Grid container justifyContent="space-between" alignItems="center">
        <Grid item xs={12} md={9}>
          <Typography>Some question-label related to my radiogroup</Typography>
        </Grid>
        <Grid item xs={12} md={3}>
          <Controller
            rules={{ required: true }}
            control={control}
            name="myRadioGroupName"
            render={({ field }) => (
              <FormControl component="fieldset">
                <RadioGroup row {...field}>
                  <FormControlLabel
                    value="yes"
                    control={<Radio data-testid="myRadioGroupYes" />}
                    label="Yes"
                  />
                  <FormControlLabel
                    value="no"
                    control={<Radio data-testid="myRadioGroupNo" />}
                    label="No"
                  />
                </RadioGroup>
              </FormControl>
            )}
          />
        </Grid>
      </Grid>
      {myRadioGroupValue === 'yes' && (
      <>
        <Typography>Fill the box below with any additional information</Typography>
        <TextField
          {...register('myRadioGroupName-additionalInfo')}
          placeholder="Enter relevant additional information"
          fullWidth
        />
      </>
      )}
    </Box>
  );
}

EDIT 2023-03: You can also set the defaultValue for a Controller component directly from its attributes like so:

<Controller
  name="myRadioGroupName"
  rules={{ required: true }}
  defaultValue={null}
  render={({ field }) => (
    ...
  )}
/>

Upvotes: 1

Related Questions