Adding A Robust Form Validation To React Redux Apps

rajaraodv
rajaraodv
Mar 8, 2016 · 7 min read

Quick Refresher

Implementing redux-form

1. Implementing redux-form — Add it’s reducer

import { combineReducers } from ‘redux’;
import PostsReducer from ‘./reducer_posts’;
import { reducer as formReducer } from ‘redux-form’;
//combineReducers adds all reducers into a single JSON of reducers
const rootReducer = combineReducers({
posts: PostsReducer, //← Posts
form: formReducer // ← redux-form
});
export default rootReducer;

2: Implementing redux-form — Update Container Component

3. Implementing redux-form — Update Presentational Component

Scenario 1 : Add Client-side Validation

STEP 1.1 Client-side Validation — Update PostsformContainer

//Client side validation
function validate(values) {
const errors = {};
if (!values.title || values.title.trim() === ‘’) {
errors.title = ‘Enter a Title’;
}
if (!values.categories || values.categories.trim() === ‘’) {
errors.categories = ‘Enter categories’;
}
if(!values.content || values.content.trim() === ‘’) {
errors.content = ‘Enter some content’;
}
return errors;
}
export default reduxForm({
form: ‘PostsNewForm’, // ←A Unique name
fields: [‘title’, ‘categories’, ‘content’], //←Fields to track
validate //← Callback function for client-side validation
}, mapStateToProps, mapDispatchToProps)(PostsForm);

STEP 1.2 Client-side Validation — Update PostsForm

const {fields: { title, categories, content }, handleSubmit} = this.props;
<form onSubmit={handleSubmit(this.props.createPost.bind(this))}>
<input type=”text” className=”form-control” {…title} />
<div className=”help-block”>
{title.touched ? title.error : ‘’}
</div>

Scenario 2: Add Instant Server Validation

STEP 2.1 Create Actions, Action Creators and Reducers

STEP 2.2 Instant Server Check — Add Callback

//For instant async server validation
const asyncValidate = (values, dispatch) => {
return new Promise((resolve, reject) => { dispatch(validatePostFields(values))
.then((response) => {
let data = response.payload.data;
let status = response.payload.status;
//if there is an error
if(status != 200 || data.title || data.categories....) {
//let other comps know of error by updating redux` state
dispatch(validatePostFieldsFailure(response.payload));
reject(data); //this is for redux-form itself
} else { //let other comps know success by updating redux` state
dispatch(validatePostFieldsSuccess(response.payload));
resolve();//this is for redux-form itself
}
}); //dispatch
}); //promise
};

STEP 2.2 Instant Server Check — Add to Redux-form config

export default reduxForm({
...
asyncValidate, //←A Callback for instant server validation
asyncBlurFields: [‘title’], //← Fields to track for instant check
...
}, mapStateToProps, mapDispatchToProps)(PostsForm);

STEP 2.3 Instant Server Check — Update PostsForm

const {asyncValidating, fields: ..., handleSubmit} = this.props;<div className=”help-block”>
{asyncValidating === ‘title’? ‘validating..’: ‘’}
</div>

Scenario 3: OnSubmit Server-side Validation

STEP 3.1 OnSubmit Validation — Update PostsformContainer

//For any field errors upon submission (i.e. not instant check)//Note: In the below function, we kinda assume that the fields are valid and try to create post and handle errors if any later on.
const validateAndCreatePost = (values, dispatch) => {

return new Promise((resolve, reject) => {
dispatch(createPost(values)).then((response) => {
let data = response.payload.data;
//error..
if(response.payload.status != 200) {
//let other components know by updating the redux` state
dispatch(createPostFailure(response.payload));
reject(data); //this is for redux-form itself
} else {
//let other components by updating the redux` state
dispatch(createPostSuccess(response.payload));
resolve();//this is for redux-form itself
}
});//dispatch
});//return};
const mapDispatchToProps = (dispatch) => {
return {
createPost: validateAndCreatePost,
resetMe: () =>{
dispatch(resetNewPost());
}
}
}

Scenario 4: Prevent Duplicate submission

4.1. Update PostsForm

const {asyncValidating, fields: { title, categories, content }, handleSubmit, submitting } = this.props;
<button type=”submit” className=”btn btn-primary” disabled={submitting} >Submit</button>

My Other Blogs

ES6

WebPack

Draft.js

React And Redux :

Salesforce

rajaraodv

Written by

rajaraodv

Trying to make Web development simple. Former Developer Advocate @Salesforce, VMware (node.js); Engineer @ Yahoo, Zimbra. Twitter: @rajaraodv

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade