- Redux Form
- Examples
- Synchronous Validation Example
Synchronous Validation Example
There are two ways to provide synchronous client-side validation to your form.
The first is to provide redux-form with a validation function that takes an object of form values and returns an object of errors. This is done by providing the validation function to the decorator as a config parameter, or to the decorated form component as a prop.
The second is to use individual validators for each field. See Field-Level Validation Example.
Additionally, you can provide redux-form with a warn function with the same type signature as your validation function. Warnings are errors that do not mark a form as invalid, allowing for two tiers of severity for errors.
The example validation function is purely for simplistic demonstration value. In your application, you will want to build some type of reusable system of validators.
Notice the reused stateless function component used to render each field. It is
important that this not be defined inline (in the render()
function), because
it will be created anew on every render and trigger a rerender for the field,
because the component
prop will have changed.
IMPORTANT: If the validation function returns errors and the form does not currently render fields for all of the errors, then the form will be considered valid and will be submitted.
IMPORTANT: Synchronous validation happens on every change to your form data,
so, if your field value is invalid, your field.error value will always be
present. You will probably only want to show validation errors once your field
has been touched, a flag that is set for you by redux-form
when the onBlur
event occurs on your field. When you submit the form, all the fields are marked
as touched, allowing any of their validation errors to show.
IMPORTANT: In your validate function, values can be undefined
, so pay attention when you are validating nested fields. If not, you could encounter some TypeError: undefined is not an object
.
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:syncValidation
or manually run the following
commands:
cd ./examples/syncValidation
npm install
npm start
Form
Values
undefined
Code
SyncValidationForm.js
import React from 'react'
import { Field, reduxForm } from 'redux-form'
const validate = values => {
const errors = {}
if (!values.username) {
errors.username = 'Required'
} else if (values.username.length > 15) {
errors.username = 'Must be 15 characters or less'
}
if (!values.email) {
errors.email = 'Required'
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address'
}
if (!values.age) {
errors.age = 'Required'
} else if (isNaN(Number(values.age))) {
errors.age = 'Must be a number'
} else if (Number(values.age) < 18) {
errors.age = 'Sorry, you must be at least 18 years old'
}
return errors
}
const warn = values => {
const warnings = {}
if (values.age < 19) {
warnings.age = 'Hmm, you seem a bit young...'
}
return warnings
}
const renderField = ({
input,
label,
type,
meta: { touched, error, warning }
}) => (
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type} />
{touched &&
((error && <span>{error}</span>) ||
(warning && <span>{warning}</span>))}
</div>
</div>
)
const SyncValidationForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field
name="username"
type="text"
component={renderField}
label="Username"
/>
<Field name="email" type="email" component={renderField} label="Email" />
<Field name="age" type="number" component={renderField} label="Age" />
<div>
<button type="submit" disabled={submitting}>
Submit
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'syncValidation', // a unique identifier for this form
validate, // <--- validation function given to redux-form
warn // <--- warning function given to redux-form
})(SyncValidationForm)