Search code examples
validationreact-nativeredux-formwizardreact-native-flatlist

Can I do multiple validations in a wizard type form?


I am building out a wizard-like form in react-native using the redux-form package but am not conditionally rendering each step like in the example.

Certain important design requirements:

  1. The continue button is disabled until each step with multiple fields are valid.
  2. I need to animate the transition between each step and also show an animated progress bar underneath it all.

So far, I have all my different steps built into a horizontal FlatList component and it works, but, since fields from other steps are rendered and not yet valid, I have no way to disable the Continue button on a per-step basis using the this.props.invalid flag which is what I originally tried to do. In the example, the submit button for each step is enabled which allows you to submit the form and trigger any pending validations for the current step.

My question is: is there a way to group these individual fields and get some type of updated prop in order to consider the step valid or can I use a different form name for each step and then merge the different steps/forms when submitting the final one?

Appreciate any insights into this type of setup with redux-forms, thanks!


Solution

  • I solved my issue by using the redux form getFormSyncErrors selector.

    import { 
      reduxForm,
      Field,
      getFormSyncErrors 
    } from 'redux-form';
    

    First you create your selector which will add a syncErrors prop with an array of fields that currently fail your sync validation rules.

    Component = connect(
      state => ({
        syncErrors: getFormSyncErrors('formName')(state)
      })
    )(Component);
    

    Then in my component I compare the fields that need validation for the current step and check for their presence in the syncErrors array. If no errors are present for the current step, the Continue button will be enabled.

    render(){
      const { syncErrors } = this.props;
      const fields = ['first_name', 'last_name', 'email'];
      const errorFields = syncErrors ? Object.keys(syncErrors) : [];
      const hasErrors = fields.some(el => errorFields.indexOf(el) >= 0);
    
      return(
        {...Fields}
        <ActionButton
          text='Continue'
          handleButtonPress={this.goToStep}
          disabled={this.props.pristine || hasErrors}
        />
      )
    }