48

Couldn't find a solution.
I'm using react-hook-form and I want to disable the submit button when the forms are empty and enable as long as all forms have atleast something written in them.
How would I do that using react-hook-form?

6 Answers 6

78
const { 
    register, 
    handleSubmit, 
    formState: { isSubmitting, isDirty, isValid } // here
  } = useForm({ mode: "onChange" })


<button
  type="submit"
  disabled={!isDirty || !isValid} // here
>
  Comment
</button>
Sign up to request clarification or add additional context in comments.

2 Comments

or you could get form state directly from const { isDirty, isValid } = useFormState(); if used in nested components
thank you for this. I did this for the Controller of this library and it worked.
36

The best solution I found so far using formState and by setting the mode to onChange.

 const { register, handleSubmit, formState } = useForm({
    mode: "onChange"
  });

And on the submit button:

<button disabled={!formState.isValid}/>

Based on this issue: https://github.com/react-hook-form/react-hook-form/issues/77

onChange mode explanation from the documentation:

Validation will trigger on the change event with each input, and lead to multiple re-renders. Warning: this often comes with a significant impact on performance.

Comments

3

you can use formState => isDirty which means form is been modified.

https://react-hook-form.com/api#formState

here is a working example for formState below:

https://codesandbox.io/s/react-hook-form-v6-formstate-ht098?file=/src/index.jsx:423-432

<input disable={formState.isDirty} type="submit" />

2 Comments

What if i want to disabled the submit button again after submit successful. I dont see that case mention the the doc. Thanks for the react-hook-form , it is a great lib.
This does not seem to work with controllers when using third party libraries
2
const { 
    register, 
    handleSubmit, 
    formState: { isSubmitting, isDirty } // <== isDirty
  } = useForm({ defaultValues: { ... } }) // <== defaultValues - leave your form values empty in your case


<button
  type="submit"
  disabled={!isDirty} // <== Once form is touched, this changes
>
  submit
</button>

With the above, until the form is touched, the submit button is disabled.

You can combine with isValid to ensure the form cannot be submitted until all validations pass.

Comments

0

Close but I think the logic is slightly off from the other comments. The key is to use the && operator. Credit to the example with the Formik library.

const { formState: { errors, isDirty, isValid } } = useForm()
///...
<button type="submit" disabled={!isDirty && !isValid}>
Continue
</button>

2 Comments

So when the form is dirty, yet invalid (false && true), it won't be disabled anymore? I don't think this is a suitable answer for most use cases.
I think that should be ||.
0

isDirty Set to true after the user modifies any of the inputs.

isValid Set to true if the form doesn't have any errors.

Some situations aren't good for isValid

Comments

Your Answer

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