question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

validation fails after reinitialization

See original GitHub issue

Hi, first of all congrats to this great component. Great work!

I’m combining the two website examples “Initializing from State” and “Submit Validation”. I’m using the submitted data to reinitialize the form.

The form is correctly reinitialized with the submitted data. However, after reinitializing, the validation function is called with the old initialValues. I end up with sync errors, although the data is valid.

The action sequence is this:

@@redux-form/START_SUBMIT
@@test/UPDATE_DATA (here I'm updating the state, which is used as initialValues)
@@redux-form/INITIALIZE
(in between these 2 actions, the validation function is called, with the **old** initialValues, resulting in sync errors)
@@redux-form/UPDATE_SYNC_ERRORS
@@redux-form/STOP_SUBMIT
@@redux-form/SET_SUBMIT_SUCCEEDED

It seems that the wrong values are passed in the nextProps in validateIfNeeded: reduxForm.js#L164

  • nextProps.initialValues is correctly set to the updated initalValues.
  • The problem: nextProps.values equals to this.props.initialValues. nextProps.values should either be empty or equal to the updated initialValues
screen shot 2017-01-10 at 11 28 17 screen shot 2017-01-10 at 11 28 40 screen shot 2017-01-10 at 11 28 55

Code

const initialTestState = {
    data: {
        username: ''
    }
};

const validate = values => {
  const errors = {}
  if (!values.username) {
    errors.username = 'Required'
  }
  return errors;
}; 

function submit(values, dispatch) {
  return sleep(1000) // simulate server latency
    .then(() => {
      dispatch(updateTestDataAction(values));
    })
};

let SyncValidationForm = reduxForm({
  form: 'syncValidation',  
  validate,                
  enableReinitialize: true
})(FormComponent);

SyncValidationForm = connect(
  state => ({
    initialValues: state.test.data
  })
)

I’m using redux-form 6.4.3, but I encounter the same issue with 6.3 and 6.2.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:13
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

10reactions
juanpasolanocommented, Jan 10, 2017

I’m having the same issue. Validation stops working when enableReinitialize is set to true. Only after the field is edited manually the syncErrors appear, so a user can submit a form when initialized

3reactions
d-leegcommented, Feb 10, 2017

I have been looking at the code pertaining to enableReinitialize inside reduxForm.js of version 6.5.0, and it makes little sense to me. Below is my humble attempt at suggesting a basis for a fix: The following code:

            const formState = getIn(getFormState(state) || empty, form) || empty
            const stateInitial = getIn(formState, 'initial')
            const initialized = !!stateInitial

            const shouldUpdateInitialValues = enableReinitialize && initialized && !deepEqual(initialValues, stateInitial)
            const shouldResetValues = shouldUpdateInitialValues && !keepDirtyOnReinitialize

            let initial = initialValues || stateInitial || empty

            if (shouldUpdateInitialValues) {
              initial = stateInitial || empty
            }

            let values = getIn(formState, 'values') || initial

            if (shouldResetValues) {
              values = initial
            }

Has the following problems that I can see:

  1. Why does the flag shouldUpdateInitialValues depend on whether there were initial values specified previously? Isn’t the only important thing is that we now have new initial values and that they are different than the old ones (including the case that the old ones were undefined)?

  2. Why does the if (shouldUpdateInitialValues) reuses the old initial values (found in stateInitial)? Wasn’t the meaning to actually test for the negation of this flag?

  3. Shouldn’t we update the formState with the new initial values (and the new values in case of shouldResetValues being true ) so that code coming afterwards in the file (that, in particular, runs validation etc.) will use the new data? Can this be the root cause of the issue in this thread?

In other words, shouldn’t the code look something like this:

        const formState = getIn(getFormState(state) || empty, form) || empty
        const stateInitial = getIn(formState, 'initial')

        const shouldUpdateInitialValues = enableReinitialize &&  initialValues && !deepEqual(initialValues, stateInitial);
        const initialized = !!stateInitial && !shouldUpdateInitialValues
        const shouldResetValues = shouldUpdateInitialValues && !keepDirtyOnReinitialize;
        let initial = stateInitial || empty;
        if (shouldUpdateInitialValues) {
          initial = initialValues;
          setIn(formState, 'initial', initial);
        }

        let values = getIn(formState, 'values') || initial;
        if (shouldResetValues) {
          values = empty;
          setIn(formState, 'values', initial);
        }

I guess that after these changes, we can go ahead and simplify this code:

          initIfNeeded(nextProps) {
            const { enableReinitialize } = this.props
            if (nextProps) {
              if ((enableReinitialize || !nextProps.initialized) && !deepEqual(this.props.initialValues, nextProps.initialValues)) {
                const keepDirty = nextProps.initialized && this.props.keepDirtyOnReinitialize
                this.props.initialize(nextProps.initialValues, keepDirty)
              }
            } else if (this.props.initialValues && (!this.props.initialized || enableReinitialize)) {
              this.props.initialize(this.props.initialValues, this.props.keepDirtyOnReinitialize)
            }
          }

to this:

          initIfNeeded(nextProps) {
            let props = nextProps || this.props;
            if (props.initialValues && !props.initialized) {
              props.initialize(props.initialValues, props.keepDirtyOnReinitialize);
            }
          }
Read more comments on GitHub >

github_iconTop Results From Across the Web

Validation not working after clear the form - Stack Overflow
Hi you just rest your form like that: clearall(): void { this.isEditMode = false; this.stockForm.reset(); Object.keys(this.
Read more >
Validation required field error after resetting the properties
I have an update user password form in my application which is working fine except when I reset the fields using $this->reset(['current_password', ...
Read more >
Reactive Form - Reset input validation after change
It seems that changing the entity on the left still leaves the validation error in place - but quickly fixed by adding your...
Read more >
How to reset value of an item after a failed validation?
And what do you mean by "reset"? To what? After you correct the items in error and re-submit the page, the value originally...
Read more >
Rhino 5 Validation Fails - Even After Reset - McNeel Wiki
If validation fails even after Sales has reset your license, or you are prompted to enter an upgrade key and you do not...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found