react-hook-form: Skip validations if a field is not required

Is your feature request related to a problem? Please describe. I have registered an optional text field with several validators. I think the validators should not run if the field is empty, because it’s optional, and an empty optional field is by definition valid.

The sandbox illustrates just one validation for simplicity.

Describe the solution you’d like If a field is empty and it was registered with required: false or without required specified, then skip running the validate functions.

Logical reasoning:

Here are all 6 combinations of a field (empty vs. non-empty) and required (true, false, undefined):

  • field empty
    • (1) required: true -> error already, no need to run validators
    • (2) required: false -> no error, no need to run validators because there’s nothing to validate
    • (3) required not specified -> no error, no need to run validators because there’s nothing to validate
  • field non-empty
    • (4) required: true -> no error yet, run validators for further validation
    • (5) required: false -> no error yet, run validators for further validation
    • (6) required not specified: no error yet, run validators for further validation

My proposal is to not run validators in cases (2) and (3). Validators should be run in all other cases.

The only exception I can think of for cases (2) and (3) is if the field has a validator that checks for content (minimum length, regexp match etc.), but that means the field should have been declared with { required: true } in the first place, which falls under cases (1) or (4), and validators should be run in those cases.

Describe alternatives you’ve considered

Currently, I have to prefix each validator to return true if the field value is empty:

validate: {
  rule1: value => value === '' || actualValidationLogic(value) || message;
  rule2(value) {
    if (value === '')
      return true;
    // ... actual validation logic
  }
  ...
}

This is redundant and inelegant.

Additional context

image

Benefits of adopting this proposal

  • Cleaner code. Validators no longer need to check for empty values.
  • Faster validation for empty non-required fields by skipping validation altogether.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 32
  • Comments: 36 (23 by maintainers)

Most upvoted comments

I got the solution @bluebill1049, I am realize that yup object is promise(), so if i place .min(), it’s still run the validation. So i use this solution like this. here is the codeSanbox link: https://codesandbox.io/s/boring-ramanujan-q3c54?file=/src/App.js

Is this feature added ? i also want Skip validations if a field is not required

validate: (data: string) => {
   if (!data) return true;
   
   if (data) {
     return datta === 'yes'
   }
}

image

The tooltip for that label should be “Waiting for more upvotes”?

Hi @bluebill1049, I’ve completely rewritten my proposal, clarifying the logical reasoning behind it. Please take another look? Also, if someone else might want to take a look in case I wasn’t clear and another perspective would help, or maybe they can find a counter-example - @JeromeDeLeon , @kotarella1110? Thanks everyone for your time.

I disagree, required: false is by default, it should treat differently when it’s been specified to be false.

Yeah, agree with most folks on this thread. We should skip validation checks for empty, non-required fields. This requires that we write a simple condition into every validation function. I would say this is non-expected behaviour and should be classified as a bug.

@bluebill1049 Is there a way to validate a field without it being required? Adding validation to the Controller is stopping the form from submitting. Would be good to be able to add both properties to the rules like this so that the validation can occur when the field is full but does not stop the form from submitting if the field is empty.

rules={{ required: false, validate: () => { return getValues("firstName") === "bill"; } }}

https://codesandbox.io/s/controller-rules-forked-okk7e?file=/src/App.tsx

I think for the example, when we dont use .required(), the validation form should skip to the next step. But, when we text in on not .required() and have .length() the validation should kick in. when, there is some value on that text-input.

But, Thanks @bluebill1049

have a good night.

Summarise:

you don’t need {required: false}, because it doesn’t make any difference when you did not specify required.

<input ref={register} /> === <input ref={register({ required: false })} />

I understand that you want to skip validation with required: false, however, that’s not the currently expected behavior and we are not going to change that.

what we expected is the following

<input ref={register( maxLength: 2 )} />

‘’: empty string will pass. ‘abc’: 3 characters will fail.

There is no skipping logic inside validate field function (our build-in validator), even required is not specified we are still running the other validators.

There seems to be some communication problem here… One hand you said

I disagree, required: false is by default, it should treat differently when it’s been specified to be false.

When I asked how it should be treated differently and what “it” is, the reply was

make no difference, you shouldn’t need to specify required: false.

??? It’s late here, I’ll go sleep and read the whole thread in the morning 😃

I’m not sure I understand… what should be treated differently and how, if require is omitted, vs. if require is explicitly set to false?

As far as I currently understand (but I’m new to RHF so I might be missing something), here are all 6 combinations of a field (empty vs. non-empty) and required (true, false, undefined):

  • field empty
    • (1) required: true -> error already, no need to run validators
    • (2) required: false -> no error, no need to run validators because there’s nothing to validate
    • (3) required not specified -> no error, no need to run validators because there’s nothing to validate
  • field non-empty
    • (4) required: true -> no error yet, run validators for further validation
    • (5) required: false -> no error yet, run validators for further validation
    • (6) required not specified: no error yet, run validators for further validation

Is the above table of truth correct?

If so, I’ll continue my argument. If I’m mistaken, I will revise my understanding of validation. Thanks 😃

what about the following:

validate: (value) => {
  if (value === '') return true;

  return actualValidationLogic(value) || message;
}

one line version: validate: (value) => value === '' || actualValidationLogic(value) || message