DEV Community

Cover image for How to create dynamic forms in react using react-hook-forms.
Vineet Pardhi
Vineet Pardhi

Posted on

How to create dynamic forms in react using react-hook-forms.

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, Formik, react-form, react final-form most of these the libraries are used immensely, but I would suggest you to use react-hook-forms 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
Enter fullscreen mode Exit fullscreen mode

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.

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

const MainComponent=(props)=>{
let {register, handleSubmit, errors}=useForm();
}
Enter fullscreen mode Exit fullscreen mode
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.


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';
            }
        },
    ]
};

Enter fullscreen mode Exit fullscreen mode

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.


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>
        </>

    );

}

Enter fullscreen mode Exit fullscreen mode

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

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


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>)

Enter fullscreen mode Exit fullscreen mode

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.

Discussion (11)

Collapse
pozda profile image
Ivan Pozderac

Great article!
I also prefer react-hook-form over every other form library.

I am currently working on dynamic form generation from passed object that has validation included so everything is fully customizable, this is similar approach.

Collapse
aqkhana2002 profile image
aqkhana2002

hay wondering have you done any think like where you can select or create your template as well ? what i can see in dynamic forms is just controls and there is no html they are using to at least show for user experience , rather an input may be form up to down or left to rite ..

Collapse
pozda profile image
Ivan Pozderac

Hi,

I am currently having some private stuff going on and I really didn't work on that project for quite some time now but I was thinking of providing default template and config file where you can specify which components is which input so you can have custom one if you want, something like:

import customTextInput from './CustomTextInput';
...
inputText: customTextInput,
...

I would, of course, provide documentation on required props for such custom components so they can work seamlessly.

Collapse
fmsthird profile image
fmsthird

have you tried Formik?

Collapse
pozda profile image
Ivan Pozderac

Yep. I tried react-hook-form after I worked with Formik and I found it to be more simple to use in general. They got me with simplicity of use and minimal re-rendering.

Thread Thread
fmsthird profile image
fmsthird

That's interesting. I am a newbie to React, and since then, I am using Formik. I might try react-hook for my next project.

Collapse
rahulsolankib profile image
rahulsolankib

Great explanation! Waiting for more such articles

Collapse
vineetpardhi profile image
Vineet Pardhi Author

thanks

Collapse
karlkras profile image
Karl Krasnowsky

Lots of good information here... I think. However the code samples are incomplete and disjointed. How does this all become a form? I see no exports/imports, etc, so how these all sync up is a complete mystery.
Do you have a repo that shows this in its entirety?

Collapse
rajatpattu profile image
rajatpattu

great article. great teacher

Collapse
aqkhana2002 profile image
aqkhana2002

the code is too much short cut, is there any way i can download that sample ? i am very beginner in react and wanted to work on dynamic form.