ReactJS - Uncontrolled Component



As we learned earlier, uncontrolled component does not support React based form programming. Getting a value of a React DOM element (form element) is not possible without using React api. One way to get the content of the react component is using React ref feature.

React provides a ref attribute for all its DOM element and a corresponding api, React.createRef() to create a new reference (this.ref). The newly created reference can be attached to the form element and the attached form element's value can be accessed using this.ref.current.value whenever necessary (during validation and submission).

Form programming in uncontrolled component

Let us see the step by step process to do form programming in uncontrolled component.

Step 1 − Create a reference.

this.inputRef = React.createRef();

Step 2 − Create a form element.

<input type="text" name="username" />

Step 3 − Attach the already created reference in the form element.

<input type="text" name="username" ref={this.inputRef} />

To set defalut value of an input element, use defaultValue attribute instead of value attribute. If value is used, it will get updated during rendering phase of the component.

<input type="text" name="username" ref={this.inputRef} defaultValue="default value" />

Finally, get the input value using this.inputRef.current.value during validation and submission.

handleSubmit(e) {
   e.preventDefault();

   alert(this.inputRef.current.value);
}

Creating Simple Form

Let us create a simple form to add expense entry using uncontrolled component in this chapter.

Step 1 − First, create a new react application, react-form-uncontrolled-app using Create React App or Rollup bundler by following instruction in Creating a React application chapter.

Step 2 − Open the application in your favorite editor.

Create src folder under the root directory of the application.

Create components folder under src folder.

Step 3 − Create a file, ExpenseForm.css under src folder to style the component.

input[type=text], input[type=number], input[type=date], select {
   width: 100%;
   padding: 12px 20px;
   margin: 8px 0;
   display: inline-block;
   border: 1px solid #ccc;
   border-radius: 4px;
   box-sizing: border-box;
}

input[type=submit] {
   width: 100%;
   background-color: #4CAF50;
   color: white;
   padding: 14px 20px;
   margin: 8px 0;
   border: none;
   border-radius: 4px;
   cursor: pointer;
}

input[type=submit]:hover {
   background-color: #45a049;
}

input:focus {
   border: 1px solid #d9d5e0;
}

#expenseForm div {
   border-radius: 5px;
   background-color: #f2f2f2;
   padding: 20px;
}

Step 4 − Create a file, ExpenseForm.js under src/components folder and start editing.

Step 5 − Import React library.

import React from 'react';

Import ExpenseForm.css file.

import './ExpenseForm.css'

Create a class, ExpenseForm and call constructor with props.

class ExpenseForm extends React.Component {
   constructor(props) {
      super(props);
   }
}

Create React reference for all input fields.

this.nameInputRef = React.createRef();
this.amountInputRef = React.createRef();
this.dateInputRef = React.createRef();
this.categoryInputRef = React.createRef();

Create render() method and add a form with input fields to add expense items.

render() {
   return (
      <div id="expenseForm">
         <form>
            <label for="name">Title</label>
            <input type="text" id="name" name="name" placeholder="Enter expense title" />

            <label for="amount">Amount</label>
            <input type="number" id="amount" name="amount" placeholder="Enter expense amount" />

            <label for="date">Spend Date</label>
            <input type="date" id="date" name="date" placeholder="Enter date" />

            <label for="category">Category</label>
            <select id="category" name="category" >
               <option value="">Select</option>
               <option value="Food">Food</option>
               <option value="Entertainment">Entertainment</option>
               <option value="Academic">Academic</option>
            </select>

            <input type="submit" value="Submit" />
         </form>
      </div>
   )
}

Add an event handler for the submit action.

onSubmit = (e) => {
   e.preventDefault();

   let item = {};

   item.name = this.nameInputRef.current.value;
   item.amount = this.amountInputRef.current.value;
   item.date = this.dateInputRef.current.value;
   item.category = this.categoryInputRef.current.value;

   alert(JSON.stringify(item));
}

Attach the event handlers to the form.

render() {
   return (
      <div id="expenseForm">
         <form onSubmit={(e) => this.onSubmit(e)}>
            <label for="name">Title</label>
            <input type="text" id="name" name="name" placeholder="Enter expense title" 
               ref={this.nameInputRef} />

            <label for="amount">Amount</label>
            <input type="number" id="amount" name="amount" placeholder="Enter expense amount" 
               ref={this.amountInputRef} />      

            <label for="date">Spend Date</label>
            <input type="date" id="date" name="date" placeholder="Enter date" 
               ref={this.dateInputRef} />

            <label for="category">Category</label>
            <select id="category" name="category" 
               ref={this.categoryInputRef} >
               <option value="">Select</option>
               <option value="Food">Food</option>
               <option value="Entertainment">Entertainment</option>
               <option value="Academic">Academic</option>
            </select>

            <input type="submit" value="Submit" />
         </form>
      </div>
   )
}

Finally, export the component.

export default ExpenseForm

The complete code of the ExpenseForm component is given below

import React from 'react';
import './ExpenseForm.css'

class ExpenseForm extends React.Component {
   constructor(props) {
      super(props);

      this.nameInputRef = React.createRef();
      this.amountInputRef = React.createRef();
      this.dateInputRef = React.createRef();
      this.categoryInputRef = React.createRef();
   }
   onSubmit = (e) => {
      e.preventDefault();
      let item = {};
      item.name = this.nameInputRef.current.value;
      item.amount = this.amountInputRef.current.value;
      item.date = this.dateInputRef.current.value;
      item.category = this.categoryInputRef.current.value;

      alert(JSON.stringify(item));
   }
   render() {
      return (
         <div id="expenseForm">
            <form onSubmit={(e) => this.onSubmit(e)}>
               <label for="name">Title</label>
               <input type="text" id="name" name="name" placeholder="Enter expense title" 
                  ref={this.nameInputRef} />

               <label for="amount">Amount</label>
               <input type="number" id="amount" name="amount" placeholder="Enter expense amount" 
                  ref={this.amountInputRef} />   

               <label for="date">Spend Date</label>
               <input type="date" id="date" name="date" placeholder="Enter date" 
                  ref={this.dateInputRef} />

               <label for="category">Category</label>
               <select id="category" name="category" 
                  ref={this.categoryInputRef} >
                 <option value="">Select</option>
                 <option value="Food">Food</option>
                 <option value="Entertainment">Entertainment</option>
                 <option value="Academic">Academic</option>
               </select>
              
               <input type="submit" value="Submit" />
           </form>
         </div>
      )
   }
}
export default ExpenseForm;

index.js

Next, create a file, index.js under the src folder and use ExpenseForm component.

import React from 'react';
import ReactDOM from 'react-dom';
import ExpenseForm from './components/ExpenseForm'

ReactDOM.render(
   <React.StrictMode>
      <ExpenseForm />
   </React.StrictMode>,
   document.getElementById('root')
);

index.html

Finally, create a public folder under the root folder and create index.html file.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React App</title>
   </head>
   <body>
      <div id="root"></div>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

Next, serve the application using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

root folder

Finally, enter a sample expense detail and click submit. The submitted data will be collected and showed in a pop-up message box.

root folders
Advertisements