15

I want to check in a RHF if the user has modified the form values with the isDirty parameter.

Setting the defaultValues manually works:

const {handleSubmit, control, setValue, setError, setFocus} = useForm({defaultValues: {name: ""}});

This seem to work correctly.

But when the user tries to edit a form I load the values into the form with setValue.

Now I don't know how I can set programatically the defaultValues.

How to change React-Hook-Form defaultValue with useEffect()?

This is how I do, but the answer is not really correct. The values are set, but the defaultValues don't change this way so RHF can't compare.

Make sure to provide all inputs' defaultValues at the useForm, so hook form can have a single source of truth to compare whether the form is dirty.

https://react-hook-form.com/api/useform/formstate

How can I set the defaultValues dynamically so it even works in 'edit' mode?

6
  • 2
    have you tried reset({...defaultValues})? Commented Jan 11, 2022 at 9:33
  • After setting values with setValue or how? Commented Jan 11, 2022 at 9:35
  • 2
    no, you don't have to use setValue in order to set the defaultValue. Make an object of defaultValue in useEffect. Define all the neccasory fields like in your case name. Do something like defaultValue.name = 'Kristof' and at last do reset({...defaultVales}). Also checkout `reset`` for more clarification. react-hook-form.com/api/useform/reset Commented Jan 11, 2022 at 10:07
  • Here's the code sandbox link I've created. codesandbox.io/embed/… Commented Jan 11, 2022 at 10:14
  • Yes, you were right! It is much simpler and also easier to reset the form with reset and not use setValue at all! Thanks for your help! Maybe if you can make this comment an answer, I can accept that. Commented Jan 11, 2022 at 10:23

4 Answers 4

37

It would be easier for you to use reset() to set the defaultValue of your form. Here's an example on CodeSandbox I have prepared for you.

All you have to do is to create an object inside useEffect(). Set your all default values using that object. At last spread that defaultValues object inside reset().

  useEffect(() => {
    let defaultValues = {};
    defaultValues.firstName = "Kristof";
    defaultValues.lastName = "Rado";
    reset({ ...defaultValues });
  }, []);

  <input {...register("firstName")} placeholder="First Name" />
  <input {...register("lastName")} placeholder="Last Name" />

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks! The only missing piece in the docs was the difference between setValue and reset. However if you pre-fill a form I would now suggest for everyone to use reset. That way you can update all fields with one call (setValue can update 1 field) and also the dirtyFields and isDirty will work correctly.
Thank you! reset did the trick for me, I was trying to initialize the form values inside useFocusEffect but when running validation it was always empty, doing reset did the trick with the pre-fill
Be sure not to reset with null or undefined values because it might reset to the previous default value instead of the new one.
doesn't look like a crutch?
1

For future generations, remember to pass and set the value prop on you TextInput. I didn't do that and couldn't figure out why the value is set, but not displayed.

2 Comments

how would that look like in the context of the example provided ?
@jmiguel77 it concerns controlled components only, refer to the docs to learn which control props do what - ref, onClick, value etc.
0

I had the same issue! I was able to fix it by using the useEffect hook. Here's an example that worked for me:

  const { isLoaded, user } = useUser();

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
  });
  useEffect(() => {
    if (user?.firstName) form.setValue('first_name', user?.firstName);
    if (user?.lastName) form.setValue('last_name', user.lastName);
    if (user?.primaryPhoneNumber) form.setValue('phone', user.primaryPhoneNumber.phoneNumber);

  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user]);

Comments

0

If you want to set default values of individual fields you can also use the resetField method. Contrary to useing setValue you keep the intended behaviour from isDirty and future resets will properly restore these values.

This comes in handy if you have different parts of the form for whom data needs to be retrieved individually and asynchronously.

const { resetField } = useForm();

useEffect(() => {
   resetField('fieldId', {defaultValue:newDefaultValue});
},[newDefaultValue])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.