Submit Validation Example

The recommended way to do server-side validation with redux-form is to return a rejected promise from the onSubmit function. There are two ways to give redux-form a function to run when your form is submitted:

  1. Pass it as an onSubmit prop to your decorated component. In which case, you would use onSubmit={this.props.handleSubmit} inside your decorated component to cause it to fire when the submit button is clicked.
  2. Pass it as a parameter to the this.props.handleSubmit function from inside your decorated component. In which case, you would use onClick={this.props.handleSubmit(mySubmit)} inside your decorated component to cause it to fire when the submit button is clicked.

The errors are displayed in the exact same way as validation errors created by Synchronous Validation, but they are returned from the onSubmit function wrapped in a SubmissionError. This is to differentiate validation errors from I/O errors, like HTTP 400 or 500 errors, which will also cause the submission promise to be rejected.

Also note that a general form-wide error can be returned via the special _error key.

Running this example locally

To run this example locally on your machine clone the redux-form repository, then cd redux-form to change to the repo directory, and run npm install.

Then run npm run example:submitValidation or manually run the following commands:

cd ./examples/submitValidation
npm install
npm start

How to use the form below:

  • Usernames that will pass validation: john, paul, george, or ringo.
  • Valid password for all users: redux-form.

Form

Values

undefined

Code

submit.js

import {SubmissionError} from 'redux-form'

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

function submit(values) {
  return sleep(1000).then(() => {
    // simulate server latency
    if (!['john', 'paul', 'george', 'ringo'].includes(values.username)) {
      throw new SubmissionError({
        username: 'User does not exist',
        _error: 'Login failed!'
      })
    } else if (values.password !== 'redux-form') {
      throw new SubmissionError({
        password: 'Wrong password',
        _error: 'Login failed!'
      })
    } else {
      window.alert(`You submitted:\n\n${JSON.stringify(values, null, 2)}`)
    }
  })
}

export default submit

SubmitValidationForm.js

import React from 'react'
import {Field, reduxForm} from 'redux-form'
import submit from './submit'

const renderField = ({input, label, type, meta: {touched, error}}) => (
  <div>
    <label>{label}</label>
    <div>
      <input {...input} placeholder={label} type={type} />
      {touched && error && <span>{error}</span>}
    </div>
  </div>
)

const SubmitValidationForm = props => {
  const {error, handleSubmit, pristine, reset, submitting} = props
  return (
    <form onSubmit={handleSubmit(submit)}>
      <Field
        name="username"
        type="text"
        component={renderField}
        label="Username"
      />
      <Field
        name="password"
        type="password"
        component={renderField}
        label="Password"
      />
      {error && <strong>{error}</strong>}
      <div>
        <button type="submit" disabled={submitting}>Log In</button>
        <button type="button" disabled={pristine || submitting} onClick={reset}>
          Clear Values
        </button>
      </div>
    </form>
  )
}

export default reduxForm({
  form: 'submitValidation' // a unique identifier for this form
})(SubmitValidationForm)