- Redux Form
- Examples
- Async Validation Example
Async Change Validation Example
The recommended way to provide server-side validation is to use Submit Validation, but there may be instances when you want to run server-side validation while the form is being filled out. The classic example of this letting someone choose a value, like a username, that must be unique within your system.
To provide asynchronous validation, provide redux-form
with an asynchronous validation
function (asyncValidate
) that takes an object of form values, and the Redux dispatch
function, and returns a promise that either rejects with an object of errors or resolves.
You will also need to specify which fields should fire the asynchronous validation when
they are changed with the asyncChangeFields
config property.
Important
- Asynchronous validation will be called before the
onSubmit
is fired, but if all you care about is validationonSubmit
, you should use Submit Validation. - Asynchronous validation will not be called if synchronous validation is failing for the field just blurred.
The errors are displayed in the exact same way as validation errors created by Synchronous Validation.
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:asyncChangeValidation
or manually run the
following commands:
cd ./examples/asyncChangeValidation
npm install
npm start
Then open localhost:3030
in your
browser to view the example running locally on your machine.
How to use the form below:
- Usernames that will fail validation:
john
,paul
,george
orringo
.
Form
Values
undefined
Code
validate.js
const validate = values => {
const errors = {}
if (!values.username) {
errors.username = 'Required'
}
if (!values.password) {
errors.password = 'Required'
}
return errors
}
export default validate
asyncValidate.js
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
const asyncValidate = (values /*, dispatch */) => {
return sleep(1000).then(() => {
// simulate server latency
if (['john', 'paul', 'george', 'ringo'].includes(values.username)) {
throw { username: 'That username is taken' }
}
})
}
export default asyncValidate
AsyncValidationForm.js
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import validate from './validate'
import asyncValidate from './asyncValidate'
const renderField = ({
input,
label,
type,
meta: { asyncValidating, touched, error }
}) => (
<div>
<label>{label}</label>
<div className={asyncValidating ? 'async-validating' : ''}>
<input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
)
const AsyncValidationForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field
name="username"
type="text"
component={renderField}
label="Username"
/>
<Field
name="password"
type="password"
component={renderField}
label="Password"
/>
<div>
<button type="submit" disabled={submitting}>
Sign Up
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'asyncValidation', // a unique identifier for this form
validate,
asyncValidate,
asyncChangeFields: ['username']
})(AsyncValidationForm)