final-form / react-final-form

🏁 High performance subscription-based form state management for React
https://final-form.org/react
MIT License
7.37k stars 481 forks source link

Prevent field validation on form mount #602

Open andylacko opened 5 years ago

andylacko commented 5 years ago

bug report/feature request

What is the current behavior?

field validation runs on mount of form

<Field
  name="investorEmail"
  validateFields={[]}
  component={TextInput}
  type="email"
  withWrapper
  hint=""
  label="Investors e-mail address"
  validate={(value) => validateRequiredEmail(value, 'investorEmail', 3)}
/>

the field behaves correctly, when error is not collected through error={this.props.error || this.props.meta?.error} but only this.props.error, but I would like not to have these hacks in my code. Is there elegant solution?

What is the expected behavior?

prevent validation from running on the first render

can be acomplished by

validate={(value, values, meta) => meta.touched && validateRequiredEmail(value, 'investorEmail', 3)} , but then doesn't validate on form submit

CodeWithOz commented 5 years ago

@andylacko can you please provide a CodeSandbox link with a working example showing this behavior?

andylacko commented 5 years ago

@CodeWithOz , hi, here is sandbox

https://codesandbox.io/s/react-final-form-validation-on-mount-pw7z1?fontsize=14

try refreshing it and you will see it validates on form mount, I would like to prevent that, because of performance and also it shows error when no action was done

hope it is clear

andylacko commented 5 years ago

now I prevented displaying of error with meta?.touched && condition, it works pretty fine, but why would I want to run every validation on form mount? sometimes, when I open forms, that are fired after modal opening it lags because of form first render. Is there possibility to turn it off and keep the first validation on edit for eg?

CodeWithOz commented 5 years ago

@andylacko yes I see what you're saying. Try using meta.modified instead of meta.touched. I don't know of a particular way to opt out of the validation on mount, but you can use meta.modified to make sure your validation is called only after a change has been made.

See my modified sandbox. Let me know if this works for you.

CodeWithOz commented 5 years ago

@andylacko I hadn't saved my changes when I posted that comment, so if you already clicked on the sandbox link you may need to refresh the browser tab to get my changes. I have saved my changes now so if you haven't yet visited the link then you should see my changes whenever you do. 😄

andylacko commented 4 years ago

This seems ok, but when you want to use form for CREATE and UPDATE at the same time, meta.modified is useless when creating new entry. The form doesn't validate correctly on submit ..

jgtamayo commented 4 years ago

I face this problem and it does not happen in the form render, what happens here is the react-final-form by default validates all the fields when a specific field is validated, that is given by a property in Field called validateFields ( see https://final-form.org/docs/react-final-form/types/FieldProps), this property by default is undefined and when it has that value it validates all the fields of the form, to avoid that you must put validateFields = { []} in all your fields of the form. I think that this undermines performance and can be done in a better way, for example, by default the value is an empty array or another way that does not force you to configure all your fields. I hope my contribution helps you.

bluSCALE4 commented 3 years ago

I typically only validate if a value is present.

const validate = (value) => {
    if (value) {
      clearTimeout(validateTimeout);
      setIndicatorActive(true);
      console.log("validation executed");
      validateTimeout = setTimeout(() => {
        setIndicatorActive(false);
      }, 1000);
      if (!value || value.length < 2) {
        return "I need something longer 💁🏻‍♀️";
      }
    } else {
      return undefined;
    }
  };
pietrofxq commented 3 years ago

I came here trying to find out how to prevent a FormSpy to call onChange on mount. I ended using lodash isEmpty together with the touched value of the form since it will always be an empty object on the first render to prevent saving the form