Home > Mobile >  Update TextField from MUI in conjunction with react-hook-form. onChange is not being called
Update TextField from MUI in conjunction with react-hook-form. onChange is not being called

Time:12-13

const [userData, setUserData] = useState({
  fullName: "",
  email: "",
}); // Local component state

const onChange = (event) => {
   console.log(event.target.value);
}; // Evente handler

<Grid container spacing={1}>
  <Grid item xs={12} sm={12}>
     <TextField
        required
        id="name"
        name="fullName"
        onChange={onChange}
        label="Name"
        InputLabelProps={{ shrink: true }}
        fullWidth
        value={userData.fullName}
        margin="dense"
       />
         <Typography variant="inherit" color="textSecondary">
           {errors.fullName?.message}
         </Typography>
 </Grid>
   <Grid item xs={12} sm={12}>
     <TextField
        required
        id="email"
        name="email"
        label="Email"
        onChange={onChange}
        fullWidth
        margin="dense"
        value={userData.email}
        {...register("email")}
        error={errors.email ? true : false}
       />
       <Typography variant="inherit" color="textSecondary">
         {errors.email?.message}
        </Typography>
   </Grid>

For some reason, onChange is not being called. I also using Yup for validation. I need to update the input value and send it to the API. But for some reason event handler is not being called

CodePudding user response:

You're overriding the onChange prop with the spread of {...register("email")} as the register call will return an object, where one property is named onChange, which RHF needs to update it's internal form state. Because of that you simply don't need your own onChange handler when you use RHF, as you could just access the current <TextField /> value via RHF directly. You just have to pass your default values either via useForm defaultValues or pass it to <Controller /> directly instead of setting it via the value prop directly.

I would also recommend to use <Controller /> as with register you are losing the functionality of setting up the correct ref for your <TextField /> input element as it is linked via the inputRef prop instead of using ref which RHF register uses. This comes in handy when you want to instantly focus a field when validiation fails upon submitting the form.

You can also use <TextField />'s error and helperText props to display your error and access it via the <Controller /> fieldState object to get the current validation error (if there is one).

<Grid container spacing={1}>
  <Grid item xs={12} sm={12}>
    <Controller 
      control={control}
      name="fullName"
      defaultValue={userData.fullName}
      render={({ field: { ref, ...field }, fieldState: { error } }) => (
        <TextField
          required
          id={field.name}
          label="Name"
          InputLabelProps={{ shrink: true }}
          fullWidth
          margin="dense"
          error={!!error}
          helperText={error?.message}
        />
      )}
    />
  </Grid>
  <Grid item xs={12} sm={12}>
   <Controller 
      control={control}
      name="email"
      defaultValue={userData.email}
      render={({ field: { ref, ...field }, fieldState: { error } }) => (
        <TextField
          required
          id={field.name}
          label="Name"
          InputLabelProps={{ shrink: true }}
          fullWidth
          margin="dense"
          error={!!error}
          helperText={error?.message}
        />
      )}
    />
  </Grid>
</Grid>


  • Related