How to Handle Inputs and Forms in React

May 18, 2020

Forms are helpful for allowing user input on a webpage. In order to setup a basic form in React, first create a new project using create-react-app (or whichever build tool you prefer).

Controlled Components

A text input will store the value of whatever the user has typed. It is useful for organizational purposes to have this information saved in our components’s state. We can use the onChange handler to update state when the user makes an input change. Once updated, the new value will be displayed under the input since React re-renders when our state changes.

 

The input below is an example of a Controlled Component because it both updates and receives it’s value from state. Try it out yourself by replacing the contents of App.js with the following

import React, { useState } from "react";

const App = () => {
  const [name, setName] = useState("");

  return (
    <div style={{ textAlign: "center" }}>
      <h2>Controlled form component:</h2>
      <input onChange={(e) => setName(e.target.value)} value={name} />
      <div>{name}</div>
    </div>
  );
};
export default App;

Here we are updating the name value with the useState() hook when the input is changed. When an input event occurs, we have acess to an event object (or e for short) from our onChange handler. We also made sure to bind our variable to the property value in our <input> to complete the two-way data binding.

 

The onChange input e.target.value refers to the current value of the input, after the key is pressed. The name we set is then reflected in the <div></div> below the input. This is a basic example of how to use a single input in React. However, for more complex examples (and probably always), we will want to wrap inputs with a form element.

Multiple Form Fields

import React, { useState } from "react";

const App = () => {
  const [data, setData] = useState({
    name: "",
    age: "",
  });

  const handleChange = (event) => {
    const { value, name } = event.target;
    setData({
      ...data,
      [name]: value,
    });
  };

  return (
    <div style={{ width: "400px", margin: "60px auto" }}>
      <form
        style={{
          display: "flex",
          flexDirection: "column",
        }}
      >
        <label htmlFor="name">Name: </label>
        <input
          type="text"
          name="name"
          onChange={(e) => handleChange(e)}
          value={data.name}
        />

        <label htmlFor="age">Age: </label>
        <input
          type="number"
          name="age"
          onChange={(e) => handleChange(e)}
          value={data.age}
        />
      </form>
      <div>
        <h2>Output</h2>
        <p>Name: {data.name}</p>
        <p>Age: {data.age}</p>
      </div>
    </div>
  );
};
export default App;

In this component, the form element wraps our input tags and captures their inputs during the handleChange event. We can get the input names and values by destructuring e.target into name and value like we did above.

 

Also in the handleChange event, you’ll notice we are setting the key value pair [name]: value onto our data object using the ES6 computed property names syntax. This means we set the property with the input’s name to be the input’s value. This logic will work for additional inputs too since every input will have a name and value.

Form Submit Event

We can also trigger the form when the submit button is clicked. This is useful when we are waiting for the user completes the form so we can send the data elsewhere. The next example uses the onSubmit handler instead of multiple onChange handlers with value properties connected to state.

import React, { useState } from "react";

const App = () => {
  const [data, setData] = useState({
    name: "",
    age: "",
  });

  const onSubmitForm = (event) => {
    event.preventDefault();
    const { name, age } = event.target;
    setData({
      name: name.value,
      age: age.value,
    });
  };
  return (
    <div style={{ width: "400px", margin: "60px auto" }}>
      <form
        onSubmit={(e) => onSubmitForm(e)}
        style={{
          display: "flex",
          flexDirection: "column",
        }}
      >
        <label htmlFor="name">Name: </label>
        <input type="text" name="name" />

        <label htmlFor="age">Age: </label>
        <input type="number" name="age" />

        <input type="Submit" />
      </form>
      <div>
        <h2>Output</h2>
        <p>Name: {data.name}</p>
        <p>Age: {data.age}</p>
      </div>
    </div>
  );
};
export default App;

When our onSubmitForm method is called we can pass along the event object, which stores all of our inputs. The default behavior is for an html page to reload whenever a form is submitted, however since we are handling the form ourselves, we will call event.preventDefault() to stop the page refresh. Next we can pull name and age from the event object and set it into state. This method is more useful when dealing with APIs where you can craft a request that gets fired when the submit button is clicked.

 

This form element listens for a onSubmit event (such as a button click) from any of its children, then passes up all of the input data in a process called event bubbling.

Third Party Form Libaries

While it makes sense to code your own forms in React, sometimes it is overkill to setup a database and email server as well… especially just for a single form. There are plenty of third-party services such as Formspree, Basin, Wufoo, and dozens of others which provide cheap form storage and email alerts. If you are hosting your site on Netlify, you can setup a simple form integration using Netlify Forms for free if you receive less than 100 submissions per month.

Conclusion

There are plenty of other considerations when using forms, such as error handling (client or server side), page caching, connecting to a database, and email servers. While there are plenty of ways to setup a form, this should give you a basic overview for how to use inputs to capture and send form data.

Other React Tutorials

React

How to Setup Dark Mode in React