I was creating Forms the wrong way all along in React.js 🤔
Tags: javascript, react, webdev, beginners
Published: 2022-08-01 10:19:41

## Introduction
When I was creating a signup form, I found myself creating dozens of useStates & then creating dozens of onChange handlers for those useStates. Something like this 🤮

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659161853469/kpTlwW5zm.png" align="center" />

Man I feel sleepy even writing this for illustration!<br />
>Also, you're welcome, for blasting your eyes with that monstrous *One Light* theme code snippet. Some amount of white is good for attention aye! 😉

So... you get the point, In this post, I'll be trying to solve this problem in an elegant manner (certainly not the BS I did in my [previous post](https://kuvambhardwaj.hashnode.dev/how-not-to-use-dozens-of-usestates-for-a-big-reactjs-form), making a buggy React Form component which no one even bothers to have a look at!)

***Let's Get Started!***

## Code
```javascript
export default function App() {

  // NOT a even a SINGLE useState babyyyyyyy! 😎

  const submitForm = (e) => {
    e.preventDefault();

    const formData = new FormData(e.target);
    const inputObject = Object.fromEntries(formData); // convert the FormData object to a JSON object

    console.log(inputObject);
  };

  return (
    <div className="App">
      <form onSubmit={submitForm}>
        <div>
          <input name="email" placeholder="email" />
        </div>

        <div>
          <input name="password" placeholder="password" />
        </div>

        <div>
          <input name="phone" placeholder="phone" />
        </div>

        <br />

        <button type="submit">Submit</button>
      </form>
    </div>
  );
}
```

>You can try this code & tinker with it in the same browser as you're viewing this post, thanks to **codesandbox** ([code link](https://codesandbox.io/s/formdata-forked-ll8jbs?file=/src/App.js:0-645))

For my beginner friends, who are new to React, what we did here was:
- wrap the input fields in an actual HTML `form` element
- define the `name` attribute of each of the input fields (can be anything, HTML uses this attribute to name the input value against it)
- create a button with no `onClick` handler but a `type` attribute set to `'submit'`
- define an `onSubmit` handler under the `form` element

After the user has done typing their details in the input, clicking on the button with `type='submit'` declared in the form, will cause the HTML `form` element to call its `onSubmit` handler i.e our `submitForm` function.

```javascript
const submitForm = (e) => {
  // 1
  e.preventDefault();

  // 2
  const formData = new FormData(e.target);
  
  // 3
  const inputObject = Object.fromEntries(formData); // convert the FormData object to a JSON object
  console.log(inputObject);
};
```

Now, we've done 3 things here:
1. call the `preventDefault` method of the HTML `FormEvent` type, passed as an argument into our function by the HTML Goddess herself (we named it `e`). This function prevents the form from continuing its default behaviour after submission which includes automatically making a GET request to the same page's URL with the form input values as payload AND reloading the page (we don't want that because **we're defining our own form submit logic whose functioning will be interrupted by a page reload**)

2. Pass the form element (referenced as `e.target`) in a `FormData` constructor & store it in our `formData` constant. 
**This will take the input elements and parse them into key-value pairs** where the key is what we defined in the `name` attribute against our inputs & the value will be their corresponding input text. All the different input text values can be retrieved using their name, something like this:
```javascript
// quite similar to the map syntax to get a key ( map.get("key") )
const email = formData.get("email")
```
Isn't that quite magical AND elegant? HTML does all the work for you from parsing the form input values to collecting the data & returning it in a map-like structure 🪄.=

3.Last but not least, we convert the `FormData` object which has our input values, to a plain JavaScript object with `Object.fromEntries( ... )`. Logging the, now created object, gives this output:

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659337512578/DKtxbevEI.png" align="left" />

**IT WORKS!**

BUT! and that's a big but (pun intended), the __cons of this approach is that you CAN'T write *Controlled Inputs*__. For that, you HAVE TO declare a `useState` & It's corresponding `onChange` handler.

__"What the hell is a controlled Input?"__

Have a look at this example

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659341263223/XQtVN3N9f.png" align="center" />

This is a controlled input in React js, but for inputs like this, we can use the hybrid approach:
- Define all the inputs in a form
- Write `useState` & `onChange` handler ONLY for those inputs that are controlled
- Then, manually set values in the formData to those controlled state variables

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659341686397/C0Bo4vmnL.png" align="center" />

<img src="https://media.giphy.com/media/qPcX2mzk3NmjC/giphy.gif" align="center" />

>P.S:
Seeing HTML automatically handling inputs for us appears to be some kind of magic and to be honest, I hate when magic is occurring BUT some amount of magic is bearable for the sake of making the developer experience good 👌🏻

---

Aaaand... that's a wrap!
Like this post, if you liked it 🙃<br>
But if you loved it? man you gotta follow me on [Twitter](https://twitter.com/bhardwajkuvam) 😉

**Bye for now!**

---