Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-hook-form and MUI FormControl

So I am trying to register some radio buttons for my form, however it will not register.

<FormControl component="fieldset" inputRef={register({ required: true })}>
  <FormLabel component="legend">Promoting</FormLabel>
  <RadioGroup aria-label="promoting" name="promoting" value={promoting} onChange={handleChange} inputRef={register({ required: true })}>
    <FormControlLabel value="business" control={<Radio  />} label="Business" />
    <FormControlLabel value="nonprofit" control={<Radio />} label="Non-Profit" />
    <FormControlLabel value="event" control={<Radio  />} label="Event" />
  </RadioGroup>
</FormControl>

I am wondering what I am doing wrong

Full code:

export default function BuildAd() {
  const [promoting, setValue] = React.useState('female');

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  const { register, handleSubmit, errors } = useForm();

  const onSubmit = data => console.log(data);
  console.log(errors);
  
  return (
    <div style={{ padding: 16, margin: 'auto', maxWidth: 600 }}>
    <CssBaseline />
    
    <Typography variant="h5" align="center" component="h2" gutterBottom>
      Create your campaign
    </Typography>
         <Paper style={{ padding: 16 }}>
              <form onSubmit={handleSubmit(onSubmit)}>
                <input type="text" placeholder="First name" name="First name" ref={register({required: true, maxLength: 80})} />
                <input type="text" placeholder="Last name" name="Last name" ref={register({required: true, maxLength: 100})} />
                <input type="text" placeholder="Email" name="Email" ref={register({required: true, pattern: /^\S+@\S+$/i})} />
                <input type="tel" placeholder="Mobile number" name="Mobile number" ref={register({required: true, minLength: 6, maxLength: 12})} />
                <select name="Title" ref={register({ required: true })}>
                  <option value="Mr">Mr</option>
                  <option value="Mrs">Mrs</option>
                  <option value="Miss">Miss</option>
                  <option value="Dr">Dr</option>
                </select>

                <input name="Developer" type="radio" value="Yes" ref={register({ required: true })}/>
                <input name="Developer" type="radio" value="No" ref={register({ required: true })}/>


                <Typography variant="h5">What are you Advertising</Typography>
                    <Box m={2}/>
                    <FormControl component="fieldset" inputRef={register({ required: true })}>
                    <FormLabel component="legend">Promoting</FormLabel>
                    <RadioGroup aria-label="promoting" name="promoting" value={promoting} onChange={handleChange} inputRef={register({ required: true })}>
                      <FormControlLabel value="business" control={<Radio inputRef={register({ required: true })} />} label="Business" />
                      <FormControlLabel value="nonprofit" control={<Radio inputRef={register({ required: true })} />} label="Non-Profit" />
                      <FormControlLabel value="event" control={<Radio inputRef={register({ required: true })} />} label="Event" />
                    </RadioGroup>
                  </FormControl>
                  
                <input type="submit" />
            </form>
      </Paper>
    </div>
  );
}
like image 917
RussellHarrower Avatar asked Dec 14 '22 08:12

RussellHarrower


1 Answers

You can fallback on controllable components by using Controller if it doesn't work.

In your case, I suspect it's because the name props passed to your RadioGroup is not the same as the name attribute when passed into native inputs like input or select.

react-hook-form V7

const { handleSubmit, control } = useForm({
  defaultValues: {
    promoting2: '',
  },
});
<FormControl component="fieldset">
  <FormLabel component="legend">Promoting</FormLabel>
  <Controller
    rules={{ required: true }}
    control={control}
    name="promoting2"
    render={({ field }) => (
      <RadioGroup {...field}>
        <FormControlLabel
          value="business"
          control={<Radio />}
          label="Business"
        />
        <FormControlLabel
          value="nonprofit"
          control={<Radio />}
          label="Non-Profit"
        />
        <FormControlLabel
          value="event"
          control={<Radio />}
          label="Event"
        />
      </RadioGroup>
    )}
  />
</FormControl>

Edit 64042394/react-hook-form-and-material-ui-formcontrol (forked)

react-hook-form V6

const { register, handleSubmit, errors, control } = useForm({
  promoting: '',
});
const onSubmit = (data) => alert(JSON.stringify(data, null, 2));
<form onSubmit={handleSubmit(onSubmit)}>
  <FormControl component="fieldset">
    <FormLabel component="legend">Promoting</FormLabel>
    <Controller
      rules={{ required: true }}
      control={control}
      name="promoting"
      as={
        <RadioGroup>
          <FormControlLabel
            value="business"
            control={<Radio />}
            label="Business"
          />
          <FormControlLabel
            value="nonprofit"
            control={<Radio />}
            label="Non-Profit"
          />
          <FormControlLabel
            value="event"
            control={<Radio />}
            label="Event"
          />
        </RadioGroup>
      }
    />
  </FormControl>

  <input type="submit" />
</form>

If you want to read the value when onChange fires, you cannot do that when passing the element to the as props:

<Controller
  {...}
  as={
    <MyComponent
      onChange={handleChange} // handleChange will never be called
    />
  }
/>

The reason is because Controller will copy the element that you pass in and pass its own onChange props that will override yours. See here and here.

To fix that problem, you need to use another way to pass the element down by using render props to gain more control on how you should render your components.

<Controller
  rules={{ required: true }}
  control={control}
  name="promoting2"
  render={({ name, onBlur, onChange, value }) => (
    <RadioGroup
      value={value}
      onBlur={onBlur}
      onChange={(e) => {
        onChange(e);
        console.log(e.target.value); // will be called this time
      }}
    >
      <FormControlLabel
        value="business"
        control={<Radio />}
        label="Business"
      />
      {...}
    </RadioGroup>
  )}
/>

Edit 64042394/react-hook-form-and-material-ui-formcontrol

like image 161
NearHuscarl Avatar answered Dec 23 '22 18:12

NearHuscarl