React Redux Form with Initial value, Validations and Props handling.

Author - Pankaj

React Redux Form simplify HTML form to store its state in Redux. With the help of React Redux Form you need not worry about single component state and it reduces number of line of code and headache. So let’s start with it to implement with new React project.

Create React App

You can easily create your new application or add in your existing application just following few steps.

// Create React App
create-react-app blogreduxform

Install redux, redux-form packages using below command.

// Install redux from
npm install –save redux-form redux

Finally run you application using below command and it will open new window in browser.

npm start

By following all below steps you have final output like below image. In this example I have tried to cover all commonly used inputs. It will be fun once you master with Redux Form.

Configure Redux Store

To use Redux form you need to add redux-form reducer with our store as shown in below code. Create src/redux/ConfigureStore.js as follow.

import { combineReducers } from 'redux';
import { reducer as reduxFormReducer } from 'redux-form';

import exampleFormReducer from '../Container/reducer';


const createReducer = combineReducers({
    form: reduxFormReducer,
    formReducer: exampleFormReducer,
});

export default createReducer;

Now create a simple form using redux-form as following code. This is a simple demonstration of how to connect all the standard HTML form elements to redux-form.

Create src/App.js as follow.

import React from 'react';

import ExampleForm from './Components/ExampleForm';
import { Provider } from 'react-redux';
import configureStore from '../src/redux/ConfigureStore';
const store = configureStore();

class App extends React.Component {
  submit = (values) => {
    this.setState({
      userParam: values
    });
  };

  render() {
    return (
      <Provider store={store}>
        <ExampleForm
          onSubmit={this.submit} />
      </Provider>
    );
  }
}

export default App;

Implement Redux Form in component. For that create src/Components/ExampleForm.js, here I am writing useful snippets of code but you will find whole code from this GitHub Repo.

Implementation for initialisation & form reset method as below.

// Form initialisation
onLoadform = () => {
        initObj = webConst.setDefaultValue(initObj);
        this.props.preLoadingDataRequest(initObj);
}
// Form reset
onResetForm = () => {
        initObj = webConst.removeDefaultValue(initObj);
        this.props.preLoadingDataRequest(initObj);
}

In the below code, you can see i have used  component from redux-form. The component connects each input to the store. It creates an HTML input element of given type (text, select, etc…). Redux Form also passes additional props such as value, onChange, onBlur, etc. Those are used to track and maintain the input state within state.

render() {
        const { invalid, handleSubmit, pristine, reset, submitting } = this.props;
        return (
            <div className="br-exple">
                <form onSubmit={handleSubmit}>

                    <div>
                        <label>Username</label>
                        <div>
                            <Field
                                validate={[formValidation.required]}
                                name={webConst.fielUserName}
                                component={formValidation.renderInputField}
                                type="text"
                                placeholder="First Name" />
                        </div>
                    </div>

                    <div>
                        <label>Email</label>
                        <div>
                            <Field
                                validate={[formValidation.required, formValidation.email]}
                                name={webConst.fielEmail}
                                component={formValidation.renderInputField}
                                type="email"
                                placeholder="Email"
                            />
                        </div>
                    </div>

                    <div>
                        <label>Phone</label>
                        <div>
                            <Field
                                validate={[formValidation.required]}
                                name={webConst.fielPhone}
                                component={formValidation.renderInputField}
                                type="number"
                                placeholder="Mobile"
                            />
                        </div>
                    </div>

                    <div>
                        <label>Sex</label>
                        <div>

                            <label>
                                <Field
                                    validate={[formValidation.required]}
                                    name={webConst.fielGender}
                                    component="input"
                                    type="radio"
                                    value="male"
                                />{' '}
                                Male
                          </label>

                            <label className="pl">
                                <Field
                                    validate={[formValidation.required]}
                                    name={webConst.fielGender}
                                    component="input"
                                    type="radio"
                                    value="female"
                                />{' '}
                                Female
                          </label>

                        </div>
                    </div>

                    <div>
                        <label>Favorite Color</label>
                        <div>
                            <Field
                                name={webConst.fielFavColor}
                                component={formValidation.renderSelectField}>
                                <option >Select any color ...</option>
                                <option value="Red">Red</option>
                                <option value="Green">Green</option>
                                <option value="Blue">Blue</option>
                            </Field>
                        </div>
                    </div>

                    <div className="el-check-row">
                        <div>
                            <Field
                                validate={[formValidation.required]}
                                name={webConst.fielEmployed}
                                id="employed"
                                component="input"
                                type="checkbox"
                            />
                        </div>
                        <label className="pl" htmlFor="employed">Employed</label>

                    </div>

                    <div>
                        <label>Notes</label>
                        <div>
                            <Field
                                validate={[formValidation.required]}
                                name={webConst.fielNotes}
                                component={formValidation.renderTextAreaField} />
                        </div>
                    </div>
                    <div className="btn-group">
                        <button className={invalid ? 'bt-active' : ''} type="submit" disabled={submitting}>Submit</button>
                        <button type="button" onClick={this.onResetForm}>Clear Preload</button>
                        <button type="button" onClick={this.onLoadform}>Preload</button>
                        <button type="button" disabled={pristine || submitting} onClick={reset}>Reset</button>

                    </div>
                </form>
            </div>
        );
    }
}

So as a summary, you have a form component (ExampleForm .js) wrapped with reduxForm(). There is one text input inside, wrapped with. The data flows like this

  • User clicks on the input,
  • “Focus action” is dispatched,
  • formReducer updates the corresponding state slice,
  • The state is then passed back to the input.

Same goes for any other interaction like filling the input, changing its state or submitting the form.
Here is redux implementation for Redux Form.

function mapStateToProps(state) {
    return {
        initialValues: state.formReducer.loadData,
    };
}

const mapDispatchToProps = {
    preLoadingDataRequest
};


ExampleForm = reduxForm({
    form: 'exampleform',
    enableReinitialize: true
})(ExampleForm);

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(ExampleForm);

Redux Form Initialisation

First you need to set up reducer like below code snippets.

const initialState = {
    isLoading: false,
    loadData: '',
    loadError: '',
};

export default function exampleFormReducer(state = initialState, action) {
    switch (action.type) {
        case LOAD:
            return {
                loadData: action.data,
                isUpdateMode: false
            };
        default:
            return state;
    }
}
export const setDefaultValue = (initObj) => {
    initObj = {
        username: 'Logistic Infotech PVT. LTD.',
        email: 'li@gmail.com',
        phone: '9898989898',
        sex: 'male',
        favoritecolor: 'Blue',
        employed: true,
        notes: 'This is an notes for testing purpose here.',
    };
    return initObj;
};
export const removeDefaultValue = (initObj) => {
    initObj = {
        username: '',
        email: '',
        phone: '',
        sex: '',
        favoritecolor: '',
        employed: false,
        notes: '',
    };
    return initObj;
};

Implementation of Redux Form Validations

Here in below code you will find simple validation rules I have implemented. You can write your own as per your requirements.

import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import '../Components/Example.scss';

export const required = (value) => {
  return value ? undefined : '*this field is required';
};

export const email = value =>
  value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) ?
    'Invalid email address' : undefined;



export const renderSelectField = ({ className, input, meta: { touched, error }, children }) => (
  <div>
    <div>
      <select className={className} {...input}>
        {children}
      </select>
      {touched && error && <span className="text-danger">{error}</span>}
    </div>
  </div>
);

export const renderInputField = ({ input, valueKey, placeholder, className, defaultValue, type, meta: { touched, error, warning } }) => {
  return (
    <Fragment>
      {valueKey !== undefined ? (
        <input {...input} autoComplete="off" placeholder={placeholder} value={valueKey} defaultValue={defaultValue} className={className} type={type} />
      ) : (
          <input {...input} autoComplete="off" placeholder={placeholder} className={className} type={type} />
        )}

      {touched && ((error && <span className="text-danger">{error}</span>) || (warning && <span>{warning}</span>))}
    </Fragment>
  );
};

export const renderTextAreaField = ({ className, input, placeholder, meta: { touched, error, warning } }) => (
  <Fragment>
    <textarea {...input} className={className} placeholder={placeholder} />
    {touched && ((error && <span className="text-danger">{error}</span>) || (warning && <span>{warning}</span>))}
  </Fragment>
);

export const confirmPassword = (value, allValues) => {
  return value !== allValues.new ? "Password don't match" : undefined;
};

export const minLength = min => value => (value && value.length < min ? `Must be ${min} characters or more` : undefined);

export const minValue6 = minLength(6);

export const noSpace = value => (value && !/^[^\s]+(\s+[^\s]+)*$/.test(value) ? 'Not allow starting or ending of space' : undefined);

export const alphaNumeric = value => (value && !/^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*)$/.test(value) ? 'Must be character include upper,lower and number' : undefined);


renderTextAreaField.defaultProps = {
  handleSubmit: () => { },
  pristine: () => { },
  reset: () => { },
  submitting: () => { },
};

renderTextAreaField.propTypes = {
  className: PropTypes.any,
  input: PropTypes.any,
  placeholder: PropTypes.any,
  meta: PropTypes.any,
};


renderInputField.defaultProps = {
  handleSubmit: () => { },
  pristine: () => { },
  reset: () => { },
  submitting: () => { },
};

renderInputField.propTypes = {
  className: PropTypes.any,
  input: PropTypes.any,
  valueKey: PropTypes.any,
  placeholder: PropTypes.any,
  defaultValue: PropTypes.any,
  type: PropTypes.any,
  meta: PropTypes.any
};

renderSelectField.defaultProps = {
  handleSubmit: () => { },
  pristine: () => { },
  reset: () => { },
  submitting: () => { },
};

renderSelectField.propTypes = {
  className: PropTypes.any,
  input: PropTypes.any,
  meta: PropTypes.any,
  children: PropTypes.any,
};

That’s it. we have integrated redux-form  with validation and initialValues in our react-app successfully… You will find latest code with example from this GitHub link.

Don’t miss the next post!

Loading

Related Posts