Forms In React

This article talks about Form and its usage and also, you will learn about Controlled and Uncontrolled components in React.

Introduction

 
In the previous article, we have learned how styles and CSS are applied in React.js and also how we can customize styled components. In this article, we will learn about the basics of the Form element and use of controlled components in React. This will also include the life cycle of components.
 

Basics of Form

 
Form in React works the same way as it works in HTML. They provide us a basic medium to the user to interact with the app. Developers depend on forms for everything. It provides security for logged in users, it also provides filtering, searching, listing, etc. The Form tag on "Submit" redirects to another page so it is better to use JavaScript functions. To achieve this functionality, we have a technique named Controlled Components.
 
React provides 2 ways to get values from Form elements - Controlled Components and Uncontrolled Components.
 

Uncontrolled Components

 
The Uncontrolled components are those components that store and maintain their own state internally. When using Uncontrolled components, `ref` keyword is used to find current value when required.
 
This pattern is not supported by React but can be used in developing when only the final state is required without worrying about intermediate state of variables. Otherwise, the controlled components technique should be used.
 
This component is just like traditional HTML forms because the input form data is stored inside DOM and not within the component. Elements like <input> and <textarea> maintain their state by themselves. We can get input values from DOM using `ref`.
 
For example -
  1. import React,{Component} from 'react';  
  2. import styled from 'styled-components';  
  3.   
  4. class UserForm extends Component{  
  5.         constructor(props){  
  6.                 super(props);  
  7.                 this.handleSubmit = this.handleSubmit.bind(this);  
  8.         }  
  9.   
  10.         handleSubmit(e){  
  11.                 alert('Inputted value is :'this.input.value);  
  12.         }  
  13.   
  14.         render(){  
  15.                 return(  
  16.                         <form onSubmit={this.handleSubmit}>  
  17.                                 <label>Enter Name</label>  
  18.                                 <textarea type="text" ref={(input) => this.input = input}></textarea>  
  19.                                 <button type="submit">Submit</button>  
  20.                         </form>  
  21.                 )  
  22.         }  
  23. }  
  24.   
  25. export default UserForm;  
The output will display as below.
 
Form Concept in React
 
Form Concept in React
 
Here, the <input> component stores its state. The ref attribute is used to create a reference to the DOM and made it accessible from where you can pull the values when needed.
 
The React prefers to use Controlled components despite Uncontrolled Components for implementing forms. Refs provide to do things in JQuery way while on the other way Controlled component provides a straightforward approach which handles form data by React component. So, if you want to integrate Non-React project with React project or any quick form development, then `ref` can be used.
 

Controlled Components

 
The Controlled component in React is used to control the values of input form elements. The React component that renders a form also controls all things that happen in the form based on user input.
 
A Controlled Components has two aspects,
  1. Controlled components have functions to handle the data going into them on every OnChange event, rather than grabbing data at once. For example, whenever user clicks submit button. This passed data is then saved to the state
  2. Data displayed by a controlled component is received through props passed down from its parent/container component.
React follows unidirectional flow which means there is a one-way loop, from child component input to parent component state and back down to child component via props. So, in Controlled component, we have 2 types of container one is a container component which is also known as smart component and other is a dumb component.
 
Container component is the one which process data, has business logic or make data calls so they are also known as Smart components while on the other hand Dumb component just receive data from the parent container. Sometimes it is possible that Dubm container triggers logic just like updating state but it is only possible by means of function which is passed from the parent component.
 
In React there are various dumb component which are just use to take user input like,
  1. <input/>
  2. <textarea/>
  3. <select/>
  4. <checkbox/>
  5. <button/>
In the below example we will check out making container components for <input/> component which will go similar for other components.
 
For example,
 
Let's take a parent component which calls an Input component that also acts as a dumb component.
 
Input.js
  1. import React from 'react';  
  2. const Input = (props) => {  
  3.          return (  
  4.                   <div class="form-group">  
  5.                            <label htmlFor={props.name} className="form-label">{props.title}</label>  
  6.                            <input name={props.name}   
  7.                                      className="form-input" id={props.name}  
  8.                                      value={props.value}  
  9.                                      placeholder ={props.placeholder}  
  10.                                      onChange={props.handleChange}/>  
  11.                  </div>  
  12.          )  
  13. }  
  14.   
  15. export default Input;  
UserForm Component
  1. import React,{Component} from 'react';  
  2. import Input from './Input';  
  3.   
  4. class UserForm extends Component{  
  5.   
  6.         constructor(props){  
  7.                 super(props);  
  8.                 this.state={  
  9.                         UserName:"",  
  10.                         handleChange : this.handleChange.bind(this)   
  11.                 }  
  12.                 this.handleSubmit = this.handleSubmit.bind(this);  
  13.         }  
  14.   
  15.         handleSubmit(e){  
  16.                 alert('Inputted value is :'this.state.UserName);  
  17.                 e.preventDefault();  
  18.         }  
  19.   
  20.         handleChange(e){   
  21.                 this.setState({  
  22.                         UserName:e.target.value  
  23.                 })  
  24.                 e.preventDefault();  
  25.         }  
  26.   
  27.         render(){  
  28.                 return(  
  29.                         <form onSubmit={this.handleSubmit}>  
  30.                                 <Input name={"inputText"} title={"FullName"}      value={this.state.UserName}  
  31.                                 placeholder={"Enter Name"}   
  32.                                 handleChange={this.state.handleChange}></Input>  
  33.                                 <button type="submit">Submit</button>  
  34.                         </form>  
  35.                  )  
  36.        }  
  37. }  
  38.   
  39. export default UserForm;  
The output for the above code will be displayed as below,
 
Form Concept in ReactForm Concept in React

Form Concept in React
 
For <select/> and <checkbox/>, we can store multiple values by allowing its multiple selection to be true and value property will contain array of value.
 
Let’s look at an example of <select/>,
 
Create Select.js component has the code as below,
  1. import React from 'react';  
  2. const Select = (props) => {  
  3.          return (  
  4.                   <div className="form-group">  
  5.                   <label htmlFor={props.name}   
  6.                             className="form-label">{props.title}</label>  
  7.                     
  8.                   <select onChange={props.handleChange}   
  9.                              name={props.name}   
  10.                              value={props.value}>  
  11.                                     <option value="" >{props.placeholder}</option>   
  12.                                     {  
  13.                                              props.options.map(option=>{  
  14.                                                       return(  
  15.                                                                <option key={option}  
  16.                                                                             value={option}  
  17.                                                                             label={option}>   
  18.                                                                </option>  
  19.                                                       );  
  20.                                            })  
  21.                                     }  
  22.                   </select>   
  23.                   </div>  
  24.           )  
  25. }  
  26.   
  27. export default Select;  
Now update UserForm.js for below,
  1. import React,{Component} from 'react';  
  2. import Input from './Input';  
  3. import Select from './Select';  
  4.   
  5. class UserForm extends Component{  
  6.          constructor(props){  
  7.                   super(props);  
  8.                   this.state={   
  9.                            UserName:"",  
  10.                            Gender:"",   
  11.                            genderOptions: ['Male''Female''Others']  
  12.                   }  
  13.   
  14.                   this.handleInput = this.handleInput.bind(this);  
  15.                   this.handleSubmit = this.handleSubmit.bind(this);   
  16.          }  
  17.   
  18.          handleSubmit(e){  
  19.                   alert('Inputted value is :'this.state.UserName + "," + this.state.Gender);  
  20.                   e.preventDefault();  
  21.          }  
  22.   
  23.          handleInput(e) {   
  24.                   let value = e.target.value;  
  25.                   let name = e.target.name;  
  26.                   this.setState( prevState => {  
  27.                            return {  
  28.                                     [name] : value   
  29.                            }  
  30.                   }, () => console.log(name + "," + value))  
  31.          }  
  32.   
  33.          render(){  
  34.                   return(  
  35.                            <form onSubmit={this.handleSubmit}>  
  36.                                     <Input name={"UserName"} title={"FullName"}
  37.                                            value={this.state.UserName}  
  38.                                            placeholder={"Enter Name"}                      
  39.                                            handleTextInput={this.handleInput}>
  40.                         </Input>  
  41.                                     <Select name={"Gender"}   
  42.                                             title="Gender"   
  43.                                             value=  {this.state.Gender}   
  44.                                             options={this.state.genderOptions}  
  45.                                             placeholder={"Select Gender"} handleChange={this.handleInput}>
  46.                                     </Select>  
  47.                                     <button type="submit">Submit</button>  
  48.                            </form>  
  49.                  )  
  50.           }  
  51. }  
  52.   
  53. export default UserForm;  
The above code will display output as below,
 
Form Concept in React

Form Concept in React
Form Concept in React
 
Now will see that for multiple select options we need to create a new event handler that stores values in an array.
 
Update UserForm.js Component,
  1. import React,{Component} from 'react';  
  2. import Input from './Input';  
  3. import Select from './Select';  
  4.   
  5. class UserForm extends Component{  
  6.            
  7.         constructor(props){  
  8.                 super(props);  
  9.                 this.state={   
  10.                         UserName:"",  
  11.                         Gender:"",  
  12.                         Skills:[""],  
  13.                         genderOptions: ['Male''Female''Others'],  
  14.                         skillOptions:         ['Programming''Development''Design''Testing']  
  15.                 }  
  16.                   
  17.                 this.handleInput = this.handleInput.bind(this);  
  18.                 this.handleChange = this.handleChange.bind(this);  
  19.                 this.handleSubmit = this.handleSubmit.bind(this);   
  20.         }  
  21.   
  22.         handleSubmit(e){  
  23.                 alert('Inputted value is :\n Name: 'this.state.UserName + "\n Gender: " + this.state.Gender + "\n Skills: " + this.state.Skills);  
  24.                 e.preventDefault();  
  25.         }  
  26.   
  27.         handleInput(e) {   
  28.                 let value = e.target.value;  
  29.                 let name = e.target.name;  
  30.                 this.setState( prevState => {  
  31.                         return {  
  32.                                 [name] : value   
  33.                         }  
  34.                 }, () => console.log(name + "," + value))  
  35.         }  
  36.   
  37.         handleChange(e) {  
  38.                 var options = e.target.options;  
  39.                 var value = [];  
  40.                 var name = e.target.name;  
  41.                 for (var i = 0, l = options.length; i < l; i++) {  
  42.                         if (options[i].selected) {  
  43.                                 value.push(options[i].value);  
  44.                         }  
  45.                 }  
  46.                 this.setState( prevState => {  
  47.                     return {  
  48.                         [name] : value   
  49.                     }}, () => console.log(name + "," + value))   
  50.        }  
  51.   
  52.         render(){  
  53.                 return(  
  54.                         <form onSubmit={this.handleSubmit}>  
  55.                                 <div class="form-group">  
  56.                                         <Input name={"UserName"}   
  57.                                                    title={"FullName"}   
  58.                                                    value={this.state.UserName}  
  59.                                                    placeholder={"Enter Name"}   
  60.                                                    handleTextInput=this.handleInput}>  
  61.                                        </Input>  
  62.                                  </div>  
  63.                                 <div class="form-group">  
  64.                                       <Select multiple={false}   
  65.                                                   name={"Gender"}   
  66.                                                   title="Gender"   
  67.                                                   value={this.state.Gender}   
  68.                                                   options={this.state.genderOptions}  
  69.                                                   placeholder={"Select Gender"}   
  70.                                                   handleChange={this.handleInput} >  
  71.                                       </Select>  
  72.                                 </div>  
  73.                               <div class="form-group">  
  74.                                      <Select multiple={true}   
  75.                                                  name={"Skills"}   
  76.                                                  title="Skills"   
  77.                                                  value={this.state.Skills}   
  78.                                                  options={this.state.skillOptions}  
  79.                                                  placeholder={"Select Skills"}   
  80.                                                  handleChange={this.handleChange} >  
  81.                                      </Select>  
  82.                              </div>  
  83.                             <button type="submit">Submit</button>  
  84.                      </form>  
  85.                )  
  86.           }   
  87. }  
  88.   
  89. export default UserForm;  
The output will display as below,
 
Form Concept in React

Form Concept in React
Form Concept in React
 
In the same way, other elements can be used to take user input. 
 
Now, we will see the difference between Controlled input and Uncontrolled input.
 

Uncontrolled Input Vs Controlled Input

 
Uncontrolled Input
Controlled Input
Uncontrolled input stores its own state internally
Controlled input stores current value in props and notifies when any changes occur which will be updated using setState.
Uncontrolled input directly has access to DOM element using ref keyword to update the current value
A parent component controls it by handling the callback and manage its own state and pass new values as props to the controlled components. This is also called Dumb Components.
Using Uncontrolled input we cannot validate input or format input or manage dynamic inputs
Using Controlled input, we can manage input validations, disabling the submit button, etc.
Uncontrolled input is often used for small applications and applications that do not require a lot of dynamic data.
Controlled input can be used for complex applications. 
 

Summary

 
In this article, we learned about Forms in React.js and also learned about Controlled and Uncontrolled components. In the next part, we will see about Component of Life Cycle in React and how it works in React
 
Next in this series >> Components Lifecycle in React