React-hook-form: with onBlur validation shouldn't isValid be false if not all required fields have been entered&validated?

Created on 17 Jun 2019  路  36Comments  路  Source: react-hook-form/react-hook-form

First of all - I love this project, clean, modern and efficient - great job.

I started using it but I feel like something may be missing.
When using onBlur validation, I would expect formState.isValid to be false until all the required fields have been touched & validated. Essentially so that the submit button can be disabled until the form isValid or 'isReadyToSubmit'....

Am I missing something? Is there another way to do this?

Thanks

enhancement question

Most helpful comment

Thanks @poteirard if you find it useful, please consider staring the repo and share among the community 馃槃 much apprecitaed 馃檹

All 36 comments

thank you for your kind words I will look into this issue.

fixed and tested with [email protected]

You want to do a quick test. once you can verify it's working. I will publish :)

Thanks for the super quick turnaround!

I tested and it does work better. However I think there Is still something that doesn't behave like I would expect.

The current implementation will set isValid once every field have been touched (and no errors are reported), regardless on whether the fields are required or not, right?

Wouldn't it be better to only set isValid only once every 'required' field have been touched (and no errors are reported)?

Because as it is currently we still can't use isValid to disable/enable a submit button, because it would require every field to be touched even if they are not required. What do you think? or did I miss something?

Thanks again and sorry I should have been more detailed in my initial comment.

you are right about that. i can take a look at this again

you want to try this version?

[email protected]

Thanks! I tried but I am getting isValid set to true by default when none of the fields have been touched yet, even as most of them are required...

do you have a codesandbox that i can play around with?

I put this one quickly together - please confirm you can access it.

https://codesandbox.io/embed/mystifying-worker-xy8pi

When we first load isValid is true... Shouldn't the initial value be false until all required fields have been touched/validated without errors?

try this version: https://codesandbox.io/s/react-hook-form-async-submit-validation-pjpbu

it's a bit more complicated than I initially thought

Looks better in initial test. will let you know if we find any other problem. Thanks for fixing this!

no worries, I have published with the new version [email protected]

i believe this is fixed, reopen when you find there is still issues.

Looks there is still a problem with isValid, when we register required field outside of the input.

https://codesandbox.io/s/goofy-shirley-cw7bh
The 'test' field is registered outside of the input component, as required. Its value is handled correctly, but isValid is never set to True...

@bluebill1049 Let me know what you think...

will take a look again.

hey @samlll42-github

With manual registered field:

useEffect(() => {
    register(
      {
        name: "test"
      },
      {
        required: true,
        min: 1
      }
    );
  }, []);

react hook form won't have a reference(ref) to the input, so it couldn't attach an event listener to watch and valid onChange or onBlur, but only onSubmit. you will have to setError or clear it manually for manually registered input.

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

let me know if those make sense.

cheers
bill

It makes sense that鈥檚 what we did for now.

but I was thinking we do update the value of required fields with setValue when they change (per the documentation), wouldn't it be possible for the React-hook-form to set isValid to true if all required fields are set, when any of the form values change including the externally registered required fields?

Right now it stays false. Or am I missing something?

yea I did thinking over this as well.
but I like an API to be as what they stated as and does less magic within (stay primitive), therefore I didn't do much extra stuff when invoking setValue or setError, but I think what you want to use is triggerValidation, which you can run after setValue.

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

let me know your thoughts. (API is not set in stone)

actually, another option would be (may not work)

setValue(
  name: Extract<Name, string>,
  value: Data[Name],
  withValidation: boolean = false,
)

I think it's a related question so I will ask here. I have a form in mode 'onBlur' and some defaultValues and I realized that when all the values are valid the "formState.isValid" is actually false. So I have to go to every input in order to activate the validation of each one. Is that the expected behaviour? Or maybe there's a way to triggerValidation to all the fields?

Thanks a lot for your work :) I'm trying to move from final-form to this library :)

Thanks, @poteirard it's not expected behavior. which version are you using? would be nice if you could share a codesandbox too :)

Hey @bluebill1049 thanks also for the fast response. I created a codesandbox with what I'm doing more or less. I'm using version 3.13.1. https://codesandbox.io/s/heuristic-currying-cvx9n

@poteirard thanks for the codesandbox, that really helped :) because you want to validate your default values.

React.useEffect(() => {
    triggerValidation([{
      name: "email"
    }, {
      name: "email2"
    }]);
  }, []);

I think this will solve your problem.

my example for validation trigger on app start: https://codesandbox.io/s/react-hook-form-seterror-9dind

hey @samlll42-github, next release: setValue('name', 'value', true) will trigger validation. The third argument is a boolean for trigger validation. hope this works for your project.

thanks a lot @bluebill1049

Don't you think it will be nice to change the implementation of triggerValidation so when you run it without parameters it triggers the validation of every field by default? I don't know if it's possible but if it is I would be more than happy to contribute with a PR :)

yes please @poteirard 鉂わ笍 great idea. PR welcome

useEffect(() => {
    triggerValidation([{ name: "password" }, { name: "passwordConfirm" }]);
  }, []);

Gives me a type error as triggerValidation doesn't accept an array, which is correct and, correct me if I'm wrong but I think the implementation is not done yet. So I suppose I have to call triggerValidation for every field one by one.

Also, I think it will be nice to have an isValid prop for each form field. But that's another topic :)

For now, I have a very strict deadline but I promise I will come back with some help on those issues.

@poteirard are you running the latest version. it should support array now :)

@samlll42-github setValue with shouldValidate is released, you happy to close this issue?

going to close this issue too, feel free to re-open is still have questions.

Not sure if related to this but I've noticed that isValid on formState doesn't update when using external validation schema (yup in this case) and onUpdate mode.

Here's a codesadbox: https://codesandbox.io/s/react-hook-form-seterror-ftvrr

This example has two fields, each required. They start off as filled in via defaultValue and the form is valid. Now try to edit the form and clear the password confirmation input. The form is still valid. If you press the TEST button the form becomes invalid.

Now if you change the mode to onChange or onBlur it works as expected, clearing the input causes the form to become invalid.

@bowd I will take a look that over the weekend. can you open a separate issue? I think this one is related to validation schema.

@poteirard FYI I have made triggerValidaiton() with an empty argument

https://github.com/bluebill1049/react-hook-form/releases/tag/v3.18.0 :)

Thanks a lot! :dancer:

Thanks @poteirard if you find it useful, please consider staring the repo and share among the community 馃槃 much apprecitaed 馃檹

Thanks @poteirard if you find it useful, please consider staring the repo and share among the community much apprecitaed

disabled={Object.keys(errors).length >0 || formState.dirtyFields.size < 5}

Was this page helpful?
0 / 5 - 0 ratings