How to create React form with a single change event handler
Tags: javascript, react, programming, productivity
Published: 2020-12-23 05:44:21

An HTML form allows users to enter data using input fields that accept text, password, email, number, color, telephone number, date, etc. Users can type lengthy texts in the textarea, can select one or many items from a select box, can check or uncheck items using a checkbox, or select one of the many options using a radio button. Once all the inputs are collected, the form can send it for further processing by using a submit button. 

Here is an example of how an HTML form may look like with elements,

![form.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1608614847498/8w6UhnMyT.png?border=1,CCCCCC&auto=compress)

Each of the form elements(`<input>`, `<textarea>`, `<select>`, etc.) can respond to DOM events. These events occur when a particular action takes place. For example, an `onchange` event occurs when the value of an element has been changed. We as web developers, listen to these changes to get the most updated values from the elements by associating a function. This function will not be executed before the event occurs.

In the example below, we have the `handleChange` function that will be executed when the value of the input textbox changes.

```html
<html>
  <body>
    <input type="text" 
            name="uname" 
            placeholder="Enter Username" 
            onchange="handleChange(this.value)">

    <script>
      function handleChange(val) {
        console.log(`The value is ${val}`);
      }
    </script>
  </body>
</html>
``` 

Usually, an HTML form may have more than one element. Some forms(like the one we have seen above) may have many. Associating different `onchange` event handler function with each of the elements to get the updated value, may result in too much code to maintain. In this article, we will see how to handle it with one function for multiple input fields in a React Form.

# React Form
The HTML form elements maintain their own state. In React, the mutable state is maintained by the `state` property of the component. Any update to this state property is possible only using the `setState()` method. The in-built react hook, `useState()` makes it, even more, easier to manage.

A good programming practice is to treat the React state as the "single source of truth". A React component with a form in it should handle everything that happens to the form when the input value changes.

> An input form element whose value is controlled by React in this way is called a “controlled component”. - [From React Docs](https://reactjs.org/docs/forms.html) 

# Handle Change Events of Multiple Controlled Components
A common trick in handling value changes of multiple controlled components is by adding the `name` attribute to each of the elements. The handler function can use the `event.target.name` to maintain the states. Let us understand it with examples.

Let's assume, we have a form with the following elements to capture user inputs,

| Field               | Type           | 
| ------------- |:-------------:|
|   fullName      | `<input type='text'>` | 
|   email            | `<input type='email'>` |   
|   password    |  `<input type='password'>` |
|   address       |  `<textarea>` |   
|   color            |  `<input type='color'>` |   
|   city              |  `<input type='text'>` |   
|   state            |  `<select>` |   
|   zip               |  `<input type='number'>` |   
|   checkMe     |  `<checkbox>` |      

## 1. Create the State as an Object
Initialize the state with default values.

```js
const [state, setState] = useState({
    fullName: "",
    email: "",
    password: "",
    address: "",
    color: "",
    city: "",
    state: "",
    zip: 0,
    checkMe: false
  })
```

## 2. Add the `name` attribute to the elements
Add the `name` attribute to all the form elements. This name attribute value should be the same as the key defined while initializing the state. Here are a few examples.

### Textbox

```html
<input type="text" 
       name="fullName" 
       value={ state.fullName } 
       onChange={ handleChange } />
```
### Email

```html
<input type="email" 
       name="email" 
       value={ state.email } 
       onChange={ handleChange } />
```
### Color

```html
<input type="color" 
       name="color" 
       value={ state.color } 
       onChange={ handleChange } />
```
### Select

```html
<select name="state" 
       onChange={ handleChange } value={ state.state }>
       <option ...>...</option>
       .....
</select>
```
### CheckBox

```html
<input type="checkbox" 
       name="checkMe" 
       checked={ state.checkMe } 
       onChange={ handleChange } />
```

## 3. Define the `handler` function
 Last is to define the handler function, `handleChange` to change the state of the component.

```js
const handleChange = evt => {
    const name = evt.target.name;
    const value =
    evt.target.type === "checkbox" ? evt.target.checked : evt.target.value;
    setState({
      ...state,
      [name]: value
    })
  }
```
Notice, we get the name of the element using `evt.target.name`. The value can be queried using the property, `evt.target.value`. As we have the `checkbox` element, we also take care of it using the `evt.target.checked`. We can also improvise further by adding another condition for the `number` type to get the value using, `evt.target.valueAsNumber`.

# See it in Action & the Source Code
Here is an example where we update the component state when the input value changes. You can see the state updates visually in the Preview section. The updated state is also applied to another component to provide user feedback.

![Flow](https://dev-to-uploads.s3.amazonaws.com/i/a0jw41rfujlrnwhyp1h8.gif)

> You can play around it from here: [https://demo.greenroots.info/react/react-multiple-input-changes/](https://demo.greenroots.info/react/react-multiple-input-changes/)

Find the Source code here,

> [Code in DemoLab](https://github.com/atapas/demolab/blob/master/code/src/demos/react/react-multiple-input-changes.js)

# Before We End...
That's all for now. I hope it was useful for you. Thank you for reading this far! Let’s connect. You can @ me on [Twitter (@tapasadhikary)](https://twitter.com/tapasadhikary) with comments, or feel free to follow.

Please like/share this article so that it reaches others as well. You may also like,
- [Understanding Dynamic imports, Lazy and Suspense using React Hooks](https://blog.greenroots.info/understanding-dynamic-imports-lazy-and-suspense-using-react-hooks-ckdfssktb01czpts12krebs1h)
- [Adding a Table row dynamically using React Hook](https://blog.greenroots.info/adding-a-table-row-dynamically-using-react-hook-ckanlxs11024p4us1zs8qljkp)
- [How to use JavaScript scheduling methods with React hooks](https://blog.greenroots.info/how-to-use-javascript-scheduling-methods-with-react-hooks-ckh1jzb0u01sg2ps1cvm4afzr)
- [A Notification Timeline using React](https://blog.greenroots.info/a-notification-timeline-using-react-ckdb6o0yp00wy59s16les9bjn)