Today, we will be going to implement creating a react dynamic form from JSON
Dynamic form in the sense, we will get an array of objects. On the basis of the individual object, we will render form fields
for eg.
{
id: 'zipCode',
type: 'input',
placeholder: 'Enter zipcode',
config: {
dataType: 'text',
placeholder: 'ZIP Code'
},
value: '',
validation: {
required: true,
minLength: 5,
maxLength: 5,
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
}
In the above object, contains a property which helps us to understand which form field we should render
like, each property denotes have some use cases, In above example type is input, so it helps to identify we need to render input field, In config, we have dataType property which helps to understand we need to render below field
<input type=text />
So, let’s develop below sample user details form using react dynamically

Please find code below
Here table of contents,
- Setting up a react project
- Creating a JSON
- Creating a UserForm container component
- Creating individual field component
Setting up a react project
we will use below command to setup starter react project
npx create-react-app dynamic-form-using-react
Above, will help you to setup starter react project, after this your folder structure will look like this

Creating a json
Here is a json below which helps to render a user form
[
{
id: 'name',
type: 'input',
placeholder: 'Enter name',
config: {
dataType: 'text',
placeholder: 'Your Name'
},
value: '',
validation: {
required: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'street',
type: 'textarea',
placeholder: 'Enter Address',
config: {
dataType: 'text',
placeholder: 'Street'
},
value: '',
validation: {
required: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'zipCode',
type: 'input',
placeholder: 'Enter zipcode',
config: {
dataType: 'text',
placeholder: 'ZIP Code'
},
value: '',
validation: {
required: true,
minLength: 5,
maxLength: 5,
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'country',
type: 'select',
placeholder: 'Enter country',
config: {
dataType: 'text',
placeholder: 'Country'
},
options: [
{
value: 'USA',
displayValue: 'United state of america'
},
{
value: 'UK',
displayValue: 'United kingdom'
},
{
value: 'IN',
displayValue: 'India'
}
],
value: '',
validation: {
required: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'email',
type: 'input',
placeholder: 'Enter email',
config: {
dataType: 'email',
placeholder: 'Your E-Mail'
},
value: '',
validation: {
required: true,
isEmail: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
]
Above is array of object, where every object represents individual form field
Creating a field component
import React from 'react';
const field = (props) => {
const fieldConfig = props.fieldConfig;
let element = null;
let classes = ['field'];
if (fieldConfig.touched && !fieldConfig.valid) {
classes.push('invalid');
}
switch (fieldConfig.type) {
case 'input':
element = (<input type={fieldConfig.config.type}
name={fieldConfig.id}
value={fieldConfig.value}
className={classes.join(' ')}
placeholder={fieldConfig.placeholder}
required={fieldConfig.validation.required}
onBlur={props.focused}
minLength={fieldConfig.validation.minLength}
onChange={props.changed}
maxLength={fieldConfig.validation.maxLength}
/>);
break;
case 'textarea':
element = <textarea
value={fieldConfig.value}
className={classes.join(' ')}
placeholder={fieldConfig.placeholder}
required={fieldConfig.validation.required}
onBlur={props.focused}
minLength={fieldConfig.validation.minLength}
onChange={props.changed}
maxLength={fieldConfig.validation.maxLength}
/>;
break;
case 'select':
element = (
<select
value={fieldConfig.value}
className={classes.join(' ')}
required={fieldConfig.validation.required}
onBlur={props.blured}
onChange={props.changed}>
<option>{fieldConfig.placeholder}</option>
{fieldConfig.options.map(option => (
<option key={option.value} value={option.value}>
{option.displayValue}
</option>
))}
</select>
);
break;
}
return (
<div className="field-wrapper">
{element}
</div>
)
}
export default field;
In the above example, As you can see we have a switch case in which on the basis of the type we are rendering a field and we passed individual JSON object to this component.
If type is text then input field will be rendered, for textarea type textarea field will be rendered, same will happen for select,
I have just added three types of form fields, you can add a checkbox, radio, etc fields.
we have also added attributes to the element for eg, placeholder, minlength, maxlength, required.
and event handlers also like onblur and onchange
Creating a userForm container
Above we have developed individual field component, let’ use that component
import React, { Component } from 'react';
import Field from '../../components/field/field'
class Form extends Component {
state = {
fields: [
{
id: 'name',
type: 'input',
placeholder: 'Enter name',
config: {
dataType: 'text',
placeholder: 'Your Name'
},
value: '',
validation: {
required: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'street',
type: 'textarea',
placeholder: 'Enter Address',
config: {
dataType: 'text',
placeholder: 'Street'
},
value: '',
validation: {
required: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'zipCode',
type: 'input',
placeholder: 'Enter zipcode',
config: {
dataType: 'text',
placeholder: 'ZIP Code'
},
value: '',
validation: {
required: true,
minLength: 5,
maxLength: 5,
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'country',
type: 'select',
placeholder: 'Enter country',
config: {
dataType: 'text',
placeholder: 'Country'
},
options: [
{
value: 'USA',
displayValue: 'United state of america'
},
{
value: 'UK',
displayValue: 'United kingdom'
},
{
value: 'IN',
displayValue: 'India'
}
],
value: '',
validation: {
required: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
{
id: 'email',
type: 'input',
placeholder: 'Enter email',
config: {
dataType: 'email',
placeholder: 'Your E-Mail'
},
value: '',
validation: {
required: true,
isEmail: true
},
valid: false,
errorMessage: 'Enter Valid data',
touched: false
},
],
formValid: false
}
fieldChange = (event, field, index) => {
const updatedField = { ...field };
updatedField.value = event.target.value;
updatedField.valid = this.checkValidity(updatedField);
const updatedFields = [...this.state.fields];
updatedFields.splice(index, 1, updatedField);
let formValid = true;
for (let field of updatedFields) {
if (!field.valid) {
formValid = false;
}
}
this.setState({
fields: updatedFields,
formValid: formValid
})
}
checkValidity = (field) => {
const rules = field.validation;
const value = field.value;
let isValid = true;
if (!rules) {
return true;
}
if (rules.required) {
isValid = value.trim() !== '' && isValid;
}
if (rules.minLength) {
isValid = value.length >= rules.minLength && isValid
}
if (rules.maxLength) {
isValid = value.length <= rules.maxLength && isValid
}
if (rules.pattern) {
isValid = rules.pattern.test(value) && isValid
}
return isValid;
}
fieldBlur(event, field, index) {
if (field.touched) {
return;
}
const updatedField = { ...field };
updatedField.touched = true;
updatedField.valid = this.checkValidity(updatedField);
const updatedFields = [...this.state.fields];
updatedFields.splice(index, 1, updatedField);
this.setState({
fields: updatedFields,
})
}
onSubmit = (event) => {
event.preventDefault();
alert('data submitted')
}
render() {
return (<form onSubmit={(event) => this.onSubmit(event)}>
{this.state.fields.map((field, index) => {
return <Field
key={field.id}
fieldConfig={field}
blured={(event) => this.fieldBlur(event,field,index)}
changed={(event) => this.fieldChange(event,field,index)} />
})}
<button type='submit'
disabled=!this.state.formValid}>
Submit
</button>
</form>)
}
}
export default Form;
In the above code, as you can see we have rendering fields array and mapping it to Field component and passing individual field as a prop to the component
also passed change and blur event,
fieldChange – method is responsible for validating individual field using checkValidity function where on the basis of config object like is it required or not, does it have minlength or maxlength and also tests pattern.
Note: we are using onBlur event for knowing that field is touched or not and if touched then only we are checking validity .
Conclusion:
This is the basic form we have developed , you can alter this with your need.Hope so you guys got some idea to develop forms dynamically using react.
If you like this tutorial, follow me on twitter for more update.