# Form Handling in React.Js

With any application, handling forms is a crucial part as we need to allow users to input and submit various information for processing. The normal way of dealing with forms in HTML such as using text inputs, checkboxes, selects, radio buttons, and so on remains true even with React.Js.

In React, you can either choose to allow the browser to handle most of the form elements and collect data through [React change events](https://www.digitalocean.com/community/tutorials/how-to-handle-dom-and-window-events-with-react), or you can use React to fully control the elements by setting and updating the input value directly. The first approach is called an uncontrolled component because React is not setting the value. The second approach is called a controlled component because React is actively updating the input.

In this article, we will check the two ways of handling forms in a React.Js application, how to submit a form (e.g. callback handler), and how to reset a form (e.g. after submission). By the end of this tutorial, you’ll be able to make a variety of forms using text inputs, checkboxes, select lists, and more.

# Prerequisite

* Have a development environment running Node.js
    
* A React development environment set up with Create React App.
    
* Basic knowledge of React such as how to manage state using `useState`, how to create components, etc.
    
* You will also need a basic knowledge of JavaScript and HTML. We will also be using [Tailwind C](https://tailwindcss.com/)SS for our styling and basic knowledge of the framework would be beneficial. However, you don't need to know Tailwind CSS as all the styling is provided.
    
* Click [Here](https://github.com/marville001/form-handling-react/tree/starter-files) to get the starter code. The code to the complete demo used in this article is provided at the end of the article.
    

## **REACT FORM BY EXAMPLE**

A common example of a form in various web applications is a login form where we capture both the email and password of the user we want to authenticate. A functional representation of such a form is as shown below

```javascript
import React from "react";

const Form = () => {
    return (
        <form className="form">
            <div className="form-group">
               <label htmlFor="email">Email</label>
               <input className="form-input" type="email" />
            </div>
            <div className="form-group">
               <label htmlFor="password">Password</label>
               <input className="form-input"  type="password" />
            </div>
            <button className="form-button">Submit</button>
        </form>
    );
};

export default Form;
```

If you click submit button, the form will reload. This is the default behavior of a form that we should prevent in our form. We need to handle the `submit` event inside the component

To handle the event, we’ll add an event handler to the `<form>` element, not the `<button>`. Create a function called `handleSubmit` that will take the `SyntheticEvent` as an argument. The`SyntheticEvent` is a wrapper around the standard `Event` object and contains the same interface. Call `.preventDefault` to stop the page from submitting the form then trigger an `alert` to show that the form was submitted:

```javascript
import React from "react";

const Form = () => {
    const handleSubmit = (event) => {
        event.preventDefault();
        alert("You have submitted the form.");
	};
	
    return (
        <form className="form" onSubmit={handleSubmit}>
            <h4>Login</h4>
            <div className="form-group">
                <label className="form-label">
                    Email
                </label>
                <input className="form-input" type="email" />
            </div>
            <div className="form-group">
                <label className="form-label">
                    Password
                </label>
                <input className="form-input"  type="password" />
            </div>
            <button className="form-button">Submit</button>
        </form>
    );
};

export default Form;
```

## Collecting Form Data Using Controlled Components

In the form above, we are rendering a simple form having two inputs one for email and the other for password. Nothing special. It is just like our regular HTML input. But to handle this input in React, we will need to understand the concept of a controlled input.

### **Uncontrolled and Controlled Input**

In a React application, an "uncontrolled input" is an input field that is not associated with a React component state. This means that the value of the input is not managed by the React component, and the component does not have direct access to the value of the input.

On the other hand, a "controlled input" is an input field that is associated with a React component state. The value of the input is managed by the React component, and the component has direct access to the value of the input. This means that the component can programmatically control the value of the input, as well as respond to changes in the input value.

We will use the controlled way to handle the input's state. The benefit of using controlled input is that we are making the component state the single source of truth for the inputs. All we have to do is declare a `state` object where data will live.

```javascript
const [email, setEmail] = useState("") // Set default value to ""
```

Now, for us to make the input field a controlled input, we assigned the state variable (which contains a default empty string) to the `value` prop.

```xml
<input className="form-input" value={email} type="text" />
```

After adding the value prop to input and assigning it to the email value from the state, if you try to write anything in the email text field, nothing will happen. This is because the `value` prop is assigned a state variable whose value is set to an empty string. And this is being forced on the input.

This is good because we now have total control over the input state. Let’s go ahead and update it. Update the code to include an `onChange` event handler.

```javascript
const handleChange = e => {
    setEmail(e.target.value)
  }
...

<input className="form-input" value={email} onChange={handleChange} id="email" type="text" />
```

React needs an `onChange` handler to keep track of any changes in the field. Anytime you write something in the input field, this `onChange` event will trigger and then call its `handleChange` function that will re-render the state using `setEmail` function.

At this point, we have a controlled email input field where its state is being managed by its component.

## Handling Multiple Inputs

In reality, you’ll be working with multiple input fields in your React application. Our example form has two inputs for email and password. In this scenario, we will make a simple adjustment not only to the handler function but also to the `input` element and the state.

We could decide to set up another `useState` Hook for the password input. Then go ahead and assign its state variable to the `value` prop. But this approach will require us to define another handler function to update the input state.

When we need to handle multiple inputs, we don’t want to make a new onChange handler function for each input. Therefore, we want to make a function that can set all values.

We can do that as follows:

```javascript
const [state, setState] = useState({
    email: "",
    password: "",
  })

const handleChange = (e)=> {
    setState({
        ...state,  
        [e.target.name]: e.target.value
    });
}
```

NB: Our form elements must have a name property with a value matching the key for the elements state. For example, the email input must have `name="email"` since we are using the key `email` on the state to store the value for that input and the password input must have `name="password"`.

Our input will change to be:

```xml
...
# Email Input
<input
    className="form-input"
    type="email"
    name="email"
    value={state.email}
    onChange={handleChange}
/>

...
# Password Input
<input
    className="form-input"
    type="password"
    name="password"
    value={state.password}
    onChange={handleChange}
/>
```

What is happening?

First, you will notice a significant change in the code. We started by modifying the `useState` Hook to include an additional input data. From there, we have access to the email and password through `state.email`and `state.password`as used in the `value` prop of their respective `input` element.

In these `input` elements, we’ve added a `name` prop that holds also their respective state name (i.e `email`and `password`). This is very important.

```javascript
import React, { useState } from "react";

const Form = () => {
    const [state, setState] = useState({
        email: "",
        password: "",
    });

    const handleChange = (e) => {
        setState((prev) => ({
            ...prev,
            [e.target.name]: e.target.value,
        }));
    };
    const handleSubmit = (event) => {
        event.preventDefault();
        alert("You have submitted the form.");
    };

    return (
        <form className="form" onSubmit={handleSubmit}>
            <h4>Login</h4>
            <div className="form-group">
                <label className="form-label">
                    Email
                </label>
                <input
                    className="form-input"
                    type="email"
                    name="email"
                    value={state.email}
                    onChange={handleChange}
                />
            </div>
            <div className="form-group">
                <label className="form-label">
                    Password
                </label>
                <input
                    className="form-input"
                    type="password"
                    name="password"
                    value={state.password}
                    onChange={handleChange}
                />
            </div>
            <button className="form-button">Submit</button>
        </form>
    );
};

export default Form;
```

Now, let’s focus on the `handleChange` function. Here, we are using the `setState` function to update the inputs state.

```javascript
const handleChange = (e)=> {
    setState({
        ...state,  
        [e.target.name]: e.target.value
    });
}
```

In this function, we are simply assigning to the element that is being targeted (through `[`[`e.target.name`](http://e.target.name)`]`) their corresponding values.

Still on the `handleChange` function. Anytime we group related data as we have it in the state variable, the state returned by the `useState` hook is not merged with that of the update passed to it. In other words, the `useState` Hook doesn’t merge the old and new state. Instead, it overrides the entire state with that of the current. So to avoid this scenario, we merge them by spreading the entire state object using the three dots before the state and overriding the part of it.

Now that you know how the control field works in React, adding any other input fields to a form will be a piece of cake. We need to update the state object to include the property for the new input, add the input, eg `textarea` to our form and add the name, value, and onChange properties to it similar to how we added them to the email and password input. Let's check some examples of other inputs.

### The TextArea Input Field

In React, the `textarea` is defined as a self-closing element just like the `input` element.

As expected, we will have the state manage the user’s input (i.e textarea message). So, update the state to include a `message` property like so:

```javascript
const [state, setState] = useState({
        email: "",
        password: "",
        message: ""
});
```

Next, add a `textarea` element in the `form` like so:

```javascript
...
return (
    <form className="form" onSubmit={handleSubmit}>
            ...
            <div className="form-group">
                <label className="form-label">
                    Message
                </label>
                <textarea
                    className="form-input"
                    name="message"
                    value={state.message}
                    onChange={handleChange}
                />
            </div>
            <button className="form-button">Submit</button>
        </form>
)
```

Take note of the `value` and `name` prop in the `textarea` element. Just like the input field, the string assigned to the `name` prop must be the same as what we declared in the state object.

### The Select Input Field

This is not different from the other input fields. As usual, we can make it a controlled input by first having the state manage the input data. Then add a `value` prop to the element and finally update it through the `onChange` handler function (but in our case, we don’t have to do anything here because we have the logic set already).

And don’t forget to add a `name` prop (to the element) that matches the name in the state. So let’s create a dropdown list with options to select car brands.

As expected, add a new property in the state. In my case, I will call it `carBrand`.

```javascript
const [state, setState] = useState({
  ...
  carBrand: "",
});
```

Then, add the `select` element just before the closing `</form>` tag:

```javascript
...
return (
    <form className="form" onSubmit={handleSubmit}>
            ...
            <div className="form-group">
                <label className="form-label">
                    Favorite Car Brand
                </label>
                <select
                    className="form-input"
                    name="carBrand"
                    value={state.carBrand}
                    onChange={handleChange}
                >
                    <option value="mercedes">Mercedes</option>
                    <option value="bmw">BMW</option>
                    <option value="audi">Audi</option>
                </select>
            </div>
            <button className="form-button">Submit</button>
        </form>
)
```

### The Checkbox Input Field

Unlike the other input fields, the checkbox uses a `checked` prop (which is a Boolean attribute) instead of the `value` prop. The idea is that a checkbox is either checked or not.

We will need to adjust the handler function to accommodate the checkbox type of input. Ok, let’s start by adding a new property to the state. We can call it `isChecked`.

```javascript
const [state, setState] = useState({
  ...
  isChecked: false,
});
```

Here, we assign a Boolean value of `false` so that the input field is unchecked by default. Next, add input checkbox just before the closing `</form>` tag.

```javascript
...
return (
    <form className="form" onSubmit={handleSubmit}>
            ...
            <div className="form-group">
                <label className="form-label">
                    <input
                        type="checkbox"
                        className="form-input"
                        name="isChecked"
                        checked={state.isChecked}
                        onChange={handleChange}
                    />
                    Remember Me?
                </label>
            </div>
            <button className="form-button">Submit</button>
        </form>
)
```

Finally, update the `handleChange` function so you have:

```javascript
const handleChange = e => {
   const value = e.target.type === "checkbox" ? e.target.checked : e.target.value; 
    setState({
        ...state,
        [e.target.name]: value
    })
}
```

In this function, we cannot use the earlier logic to manage the checkbox because it doesn’t have the `value` but `checked` attribute. So you’d need to adjust it if you want the same `handleChange` to manage the checkbox.

As seen in the handler, we now target the `type` and the `checked` attribute from this event parameter, `e`. From there, we are using the ternary operator, which is an inline if-statement to check the input types and then assign their corresponding value (either Boolean [`e.target`](http://e.target)`.checked` for the checkbox or [`e.target`](http://e.target)`.value` for every other input types).

### The Radio Input Field

The radio input types combine the input text and the checkbox type. In other words, they use both the `value` and the `checked` prop.

We will create radio inputs that allow users to select gender. As expected, let’s add that to the state.

```javascript
const [state, setState] = useState({
  ...
  gender: "",
});
```

Then, add the `radio` inputs just before the closing `</form>` tag:

```javascript
...
return (
    <form className="form" onSubmit={handleSubmit}>
            ...
            <div className="form-group">
                <label className="form-label">
                    <input
                        type="radio"
                        className="form-input"
                        name="gender"
                        value="male"
                        checked={state.gender === "male"}
                        onChange={handleChange}
                    />
                    Male
                </label>
                <label className="form-label">
                    <input
                        type="radio"
                        className="form-input"
                        name="gender"
                        value="female"
                        checked={state.gender === "female"}
                        onChange={handleChange}
                    />
                    Female
                </label>
            </div>
            <button className="form-button">Submit</button>
        </form>
)
```

What’s happening?

As you know already, once you have the state manage your input, you immediately assign the state property to the `name` prop of the input. You should know from HTML that radio group share the same name. This allows us to select only one button at a time.

Notice that the `value` prop in these inputs are static unlike that of text inputs where its value comes from the state.

And finally, with the `checked` prop, we are saying that if the condition assigned is `true`, that radio button should be checked.

Simple as that!

While working with inputs in a React application, these are the most popular and all that we cover in this article.

# Conclusion

We should handle input changes by writing controlled components. To do this, we attach an event handler function to the `onChange` event.

To handle form submission, we attach an `onSubmit` event handler to the form, and then get the `event` an object from the parameter and call `event.preventDefault` inside so we can run JavaScript code in the handler.

To handle multiple input changes with one `onChange` handler, we get the `name` and `value` properties from `event.target` from the handler’s parameter and update it with the dynamic property name feature available since ES6.

<mark>Source Code</mark> =&gt; [https://github.com/marville001/form-handling-react](https://github.com/marville001/form-handling-react)

Be on the lookout for part 2 of this blog covering form validation using libraries such as [react-hook-form](https://react-hook-form.com/) and [formik](https://formik.org/).

That's all for this article.

Thank you :)
