Home > Software design >  react-hooks-form dependent fields with Material UI TextField
react-hooks-form dependent fields with Material UI TextField

Time:11-16

With react-hooks-form I am trying to update one field based on another field value. The error I am facing is that my value is not registered in the data object.

This is my code:

const { handleSubmit, control  } = useForm({});
const [dateValue, setDateValue] = useState()

const onSubmit = (data) => {console.log(data.week)} \\ undefined


   <form
          className={classes.root}
          autoComplete="on"
          onSubmit={handleSubmit(onSubmit)}
        >
                <Controller
                  name="date"
                  control={control}
                  defaultValue={props.operation === 'edit' ? props.values.date : null}
                  render={({ field: { onChange, value }, fieldState: { error } }) => (
                    <TextField
                      id="date"
                      type="date"
                      label="date"
                      value={value}
                      className={classes.textField}
                      onChange={(event) => {
                        onChange(event.target.value); 
                        setDateValue(event.target.value);
                      }}
                      error={!!error}
                      helperText={error ? error.message : null}
                      InputLabelProps={{
                        shrink: true,
                      }}
                    />
                  )}
                  rules={{ required: 'Date is required' }}
                />


 <Controller
                        name="week"
                        control={control}
                        defaultValue=""
                        render={({ field: { onChange, value }, fieldState: { error } }) => (
                            <TextField
                                id="week"
                                type="text"
                                className={classes.textField}
                                label="week"
                                disabled={true}
                                value={dateValue}
                                onChange={onChange}
                                error={!!error}
                                helperText={error ? error.message : null}
                            />
                        )
                    />

</form>

Finally, my week value is the result of a function which returns a string containing week - year concatenation.

The value is updated in the TextField, but it is not registered in the data object. Any idea what am I missing?

CodePudding user response:

On the onChange handler of the date field you are updating only the state of dateValue and not the state of the form itself.

You have 2 options:

  1. in the onChange handler of the date field call the setValue method you get from useForm

  2. watch the value of the date field const date = watch('day') and have a useEffect to update the value of the week field:

const {watch, setValue} = useForm()

const date = watch('date')

useEffect(() => {
  const calculateWeekValue = () => {...//}
  setValue('week', calculateWeekValue(date))
}, [date, setValue])

CodePudding user response:

You can use RHF's setValue method for updating a field and call it inside the onChange handler of your first <TextField />.

So there is no need to use useState here for managing he state of your first <TextField />.

export const Demo: React.FC = () => {
  const { control, handleSubmit, setValue } = useForm();

  const onSubmit = (data) => console.log(data);

  return (
    <form autoComplete="on" onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="date"
        control={control}
        defaultValue={""}
        render={({ field: { ref, ...field }, fieldState: { error } }) => (
          <TextField
            {...field}
            onChange={({ target: { value } }) => {
              field.onChange(value);
              setValue("week", getWeek(new Date(value)));
            }}
            id="date"
            type="date"
            label="date"
            error={!!error}
            inputRef={ref}
            helperText={error?.message}
            InputLabelProps={{
              shrink: true
            }}
          />
        )}
        rules={{ required: "Date is required" }}
      />
      <Controller
        name="week"
        control={control}
        defaultValue={""}
        render={({ field: { ref, ...field }, fieldState: { error } }) => (
          <TextField
            {...field}
            id="week"
            type="text"
            label="week"
            inputRef={ref}
            error={!!error}
            helperText={error?.message}
          />
        )}
        rules={{ required: "Date is required" }}
      />
      <input type="submit" />
    </form>
  );
};

Edit ComboBox Material Demo (forked)

  • Related