redux-form: Validation not working after reset

Here is the code

import React from 'react';
import PropTypes from 'prop-types';
import { Link, Redirect } from 'react-router-dom';
import { Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { Section, RenderField, Block } from 'components';
import { validateRegisterForm as validate } from 'utils/validations';
import { forgotPassword } from 'redux/modules/auth';

const mapStateToProps = state => {
    const { sending, sendSuccess } = state.auth;

    return { sending, sendSuccess };
};

const reduxFormDecorator = reduxForm({
    form: 'ForgotPasswordForm',
    validate,
});

const reduxConnector = connect(mapStateToProps, { forgotPassword });

class ForgotPassword extends React.Component {
    static propTypes = {
        sending: PropTypes.bool,
        forgotPassword: PropTypes.func.isRequired,
        handleSubmit: PropTypes.func.isRequired,
    };

    static defaultProps = {
        sending: false,
        sendSuccess: false,
    };

    componentWillReceiveProps(nextProps) {
        if (nextProps.sendSuccess) {
            this.props.reset();
        }
    }

    handleFormSubmit = data => {
        this.props.forgotPassword(data);
    };

    render() {
        const { handleSubmit, reset, sending } = this.props;

        return (
            <div>
                <Section>
                    <div className="form-popup">
                        <div className="form-popup-content">
                            
                            <Block loading={sending}>
                                <form
                                    id="register-form"
                                    name="register-form"
                                    method="POST"
                                    onSubmit={handleSubmit(this.handleFormSubmit)}
                                >

                                    <Field
                                        name="email"
                                        type="email"
                                        component={RenderField}
                                        label="Alamat Email"
                                        description="contoh: email@example.com"
                                    />

                                    <button type="submit" className="button mid primary m-bottom-25">
                                        Reset
                                    </button>
                                </form>

                            </Block>
                        </div>
                    </div>
                </Section>
            </div>
        );
    }
}

export default reduxConnector(reduxFormDecorator(ForgotPassword));

At first validation works well. but when form is submitted and this.props.reset() is called (the input become empty) and I try to submit it again it not validate the input (input is empty).

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 29
  • Comments: 84 (3 by maintainers)

Most upvoted comments

I solved this by forcing validation using the shouldValidate config.

reduxForm({
  // Set to always validate
  shouldValidate: () => true,

  // Other config options...
})```

I’m using Redux Form 7.1.2 with React 16 and came up with this solution:

shouldError: ({ props }) => {
  return !props.anyTouched;
}

@dizlexik I do this instead: this.props.destroy(); this.props.initialize(); and works perfectly! (redux form injects those methods along with others in your component by default)

I am having the same issue but if I follow the example I can get it to work properly. Seems like you need to disable the clear button disabled={pristine || submitting}.

ReduxForm: 7.4.2 React: 16.4.0

<button type="button" disabled={pristine || submitting} onClick={reset}>
    Clear Values
</button>

https://github.com/erikras/redux-form/blob/master/examples/submitValidation/src/SubmitValidationForm.js#L36

Same for me. Seems like validate method not triggered in handleSubmit if you reset form before. And after changing any field value all works again

@umer4ik

You’re right, haven’t tested it well I guess. This one did not call handleSubmit.

shouldError: ({ props }) => {
  return props.invalid;
}

P.S. props.invalid is more “correct way”, rather than !props.anyTouched. But with this, sometimes it calls validate twice instead of one on per change and blur.

I’m also have a problem with this. shouldError: ({ props }) => { return !props.anyTouched; } doesn’t work for me. I too am using enableReinitialize. The solution for me was the aforementioned destroyOnUnmount: false workaround.

The solution with re-initializing the form instead of resetting works for me. Smth like this.props.dispatch(initialize('formName', initialFormData))

This work around is working. Make destroyOnUnMount as false. So the syncerrors and the form fields wont be unregistered.

connect(mapStateToProps, mapDispatchToProps)(reduxForm({ form: ‘myform’, validate, destroyOnUnmount: false, })

in componentWillRecieveProps, again initialize the form

componentWillReceiveProps(nextProps) { if (this.props.popUpState !== nextProps.popUpState) { this.props.initialize(); } }

Now the form is cleared on remounting and validation also works.

Here’s a replicable example in 7.0.2. https://www.webpackbin.com/bins/-KpqKYZhHDlocf2ToRfv

use this.props.initialize() instead of using this.props.reset()

@pablonm3 I do this instead: this.props.destroy(); this.props.initialize(); and works perfectly! (redux form injects those methods along with others in your component by default)

I placed form on modal and I run this.props.destroy() this.props.initialize() on handleCancel. It’s work for me just 1 times. When I close for second time, ReduxForm not trigger @@redux-form/UPDATE_SYNC_ERRORS

2 years and no solid solution. 😕

If the form is in Dialog box, destroy it completely as suggested by @shantanupaul here. Worked for my Material UI Dialog too. Does call UPDATE_SYNC_ERRORS.

fwiw, I was experiencing the same issues but calling initialize instead of reset did the trick for me.

Update: This works but it will not respect any initialValues you set in reduxForm HOC

My solution was to completely destroy the Material UI dialog on closing it and re-mounting it on opening. No other workaround worked!

Changed <Dialog open={this.state.open} ......../> to this.state.open && <Dialog open={this.state.open} ......../>

Does anyone know if a real solution is on the horizon? None of the workarounds are working for me in 7.0.3. I don’t even see destroy or initalize in my props. Maybe I’m missing something?

Thanks for the suggestion @pablonm3, but I had actually tried that before and it didn’t behave any differently than reset for me. I just tried again with the same results. Calling destroy and initialize does reset the form but it has the same effect as reset in that validations stop working. I wonder why this is working for you guys and not me 😕

If you call reset, the next call to defaultShouldValidate returns false.

That’s because it compares previous values to new values to see if it needs to validate, but it’s comparing initial values with each other because the form has already been reset.

I noticed that the reset action creator doesn’t do much. I feel like it should force the form to re-run sync validation. Otherwise I can’t think of a way to tell whether reset has run, the next time defaultShouldValidate gets called.

@hamanovich No, destroyOnUnmount: false, keepDirtyOnReinitialize: true just partially solve the issue, but validation keeps breaking.

The same error, @TheAznShumai solution helped.

import { reduxForm, getFormSyncErrors } from 'redux-form';
import { connect } from 'react-redux';
import Component from './index';

const formConfig = {
  form: 'draft',
};

const mapStateToProps = state => ({
  hasErrors: Object.keys(getFormSyncErrors(formConfig.form)(state)).length > 0,
});


export default connect(mapStateToProps)(reduxForm(formConfig)(Component));

Then in Component you have to check invalid || hasErrors to disable the button

<button disabled={invalid || hasErrors}>
   Submit
</button>

👍 Same issue.

@@redux-form/UPDATE_SYNC_ERRORS never fires are a initialize dispatched

Just to be more specific here, it only happens when i set enable enableReinitialize: true and dispatch a initialize event. If i set enableReinitialize: false but still dispatch the initialize, things works as expected so far. Best.

export default reduxForm({
  form: 'formProductUpdate',
  validate,
  enableReinitialize: true,
  destroyOnUnmount: false,
  keepDirtyOnReinitialize: true
})(ProductUpdate);

I’ve also have this problem in 7.2.0. In my case the invalid/valid props were incorrect for disabling the submit button after a form reset. I resolved my issue by manually checking if formSyncErrors exists on the form in redux using the following code.

import { getFormSyncErrors } from "redux-form";

...

const mapStateToProps = (state) => ({ hasErrors: Object.keys(getFormSyncErrors("login")(state)).length > 0 });

export default connect(mapStateToProps)(LoginForm);

I’m having the same issue. ReduxForm: 7.1.2 React: 16.0.0

Might be a workaround: Instead of calling reset, do it yourself in the reducer.

Where you put in the formReducer, use the plugin function to intercept an action of your choice in order to reset the form, as such:

const reducer = combineReducers({
  form: formReducer.plugin({
    fooForm: (state, action) => {
      switch (action.type) {
        case YOUR_ACTION_HERE:
          return {
            ...state,
            values: undefined,
          };
        default:
          return state;
      }
    },
  }),
});

I haven’t played around with the other parts of the redux store, but just returning undefined for values had the validation show up for me.

More importantly, the valid/invalid prop stays correct when I do this. For my case, if you return undefined for the entire form state, the validation only runs after user interaction, AND the valid/invalid prop is permanently broken. I have fields in multiple components, with the redux form on the highest component.