How to create dynamic forms in react using react-hook-forms.
Tags: react, webdev, javascript
Published: 2021-03-01 06:51:10

Hi guys,

If you are a React Developer you might know that Creating forms in Reactjs is quite easy, yet you need to adjust your code with a lot of things. I am going to write about a few things that you need to know while creating dynamic forms and also explain how they are written.
#### Why Dynamic Forms?
* These days, most of the big tech companies like Google, Amazon, Netflix use dynamic forms in their front-end applications since they have to handle massive scale of data and dynamic forms help to create forms that receive the schema in form of the API data, so that we don't have to worry about the fields which we are going to set in our code.
* Another reason why most of the large scale applications should use dynamic forms is that the Dynamic form component we build can be a reusable component for other components as well. which have a probability to reduce the half of our code.

#### The libraries that can be used to create dynamic forms.
There are many Libraries to create Dynamic Forms in react like [react-jsonchema-form](https://react-jsonschema-form.readthedocs.io/en/latest/), [Formik](https://github.com/formium/formik), [react-form](https://github.com/tannerlinsley/react-form), [react final-form](https://final-form.org/docs/react-final-form/getting-started]) most of these the libraries are used immensely, but I would suggest you to use __[react-hook-forms](https://react-hook-form.com/)__ because of some reasons given below.
* Almost zero dependencies.
* Very low latencies.
* Less code, since it consists of hook functions.

####Let's Get Started
To install react-hook-form in your application copy the line below
```
npm install react-hook-form
```

To view better UI try to install dependencies like react-strap/bootstrap/material, I am going to use react-strap in the example below.

To use react-hook-form follow the code below.

```Javascript
import {useForm} from 'react-hook-form';
import {Card, CardBody, Form, Row, Button} from 'reactstrap';

const MainComponent=(props)=>{
let {register, handleSubmit, errors}=useForm();
}
```

#####Creating a JSON form in Javascript
Create a component which returns a template to map the fields in the Form which we are going to create. Let's take a Basic example of Employee, you can create according to your components.


```Javascript

import React from 'react';

export const template = {
	title: 'Basic Form to Add Employee',
	Fields: [
		{
			name:'firstName' ,
			type:'text',
			title:'First Name',
			required:{
				value:true,
				message:'Employee First Name is required'
			},
			validation:function(val){
				return val.length >=5 || 'Min Length is 5';
			}
		},
		{
			name:'lastName' ,
			type:'text',
			title:'Last Name',
			required:{
				value:true,
				message:'Employee Last Name is required'
			},
			validation:function(val){
				return val.length >=5 || 'Min Length is 5';
			}
		},
	]
};

```


you can search and refer to JSON forms available on net. so that you can learn more about the schema and create different types of fields for template.
 


#####Creating a CustomForm component to render the template.
we create a function/method to renderfields and return the call the method while returning the component.
```Javascript

import React from 'react';
import {Input, Label, FormGroup, FormText, FormFeedback, Row, Col} from 'reactstrap';



//for a select input type
const renderOptions=(options)=>{
	return options.map((child)=>{
		return(
			<option key={child.value} value={child.value}>{child.label}</option>
		);
	});
};





function CustomForm({ template, data, handleform}) {
let {register,errors} = handleform;
const renderFields = (fields) => {

		return fields.map(field => {
			let { type, title, name, required,validation} = field;
			
			
switch(type){
      case 'text':
	return (
		<FormGroup key={name}>
		 <Label htmlFor={name}>
                  {title}
                  <span style={required?{color:'red'}:{}}>*</span> 
                 </Label>
                 <Input				
                  type='text'
                  name={name}						 
                  innerRef= 
               {register({required:required,validate:validation})}
                  />							 
                  {errors[name] && 
                  <FormFeedback>
                   {errors[name].message} 
                 </FormFeedback>}					
              </FormGroup>
	);
				
     case 'select':
	let {options}=field;
	return (
	  <FormGroup key={name}>
	    <Label htmlFor={name}>{title}<span style={required?{color:'red'}:{}}>*</span></Label>
	    <Input  
             type='select' 
             name={name} 
             innerRef={register}
	    >
								 
            {renderOptions(options)}
	    </Input>
          </FormGroup>
	);
				
      default:
       return (
		<div>
		  <span>Invalid Field</span>
               </div>
	);
      }
   });

};
let { title, Fields } = template;
	return (
		<>
			<h4>{title}</h4>
			<Row>
				<Col>
					{renderFields(Fields)}
				</Col>
			</Row>
		</>

	);

}

```
You can handle different types of cases and render the fields according to it.

#####Rendering CustomForm component using react-hook-form
useForm() returns Field elements to handle form in its own way.

* __register__ method allows you to register an input/select Ref and apply validation rules into React Hook Form.

* __handleSubmit__ function will pass the form data when form validation is successful and can be invoked remotely as well.

* __errors__ is an Object containing form errors and error messages corresponding to each field.

You can read more about this in the [documentation](https://react-hook-form.com/api)

So, create a return element in the App component or in whatever component in which you are going to render the form.

```JSX

let handleform={
   register:register,
   errors:errors
};
return(
<Card>
 <CardBody>
  <Form onSubmit={handleSubmit(onSubmit)}>					
   <Row className="d-flex justify-content-end">						
     <Button							 
        type='submit'							 
        className="mt-0 mr-1"							 
        color="primary">					
        Save Changes						
      </Button>
      <CustomForm  
        template={template} 
        handleform={handleform}
       />
  </Form>
 </CardBody>
</Card>)

```
you can pass the state to props in the Custom Form which have built earlier.

####Conclusion
This way you can render dynamic Forms in reactjs using react-hook-form and also it helps you with your form validation, schema and rendering.

If you like this article, share it with you dev community or with your geek folks.

**Thanks.**