Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

How to Use HTML Forms Inside React

Jun 5, 2020 • 6 Minute Read

Introduction

Forms are an essential component of any web application. They are used for search fields, contact forms, shopping checkout, sign-in or sign-up, and many other uses. Forms are required when you want to collect data from the users. A form takes input from the frontend and sends it to the backend service.

Building forms in React is slightly different from other frameworks, as you need to handle the form inputs and validations by yourself. In this guide, you will learn how to create forms in the React world and get better at it.

Forms in React

Forms in React are of two types that differ on how data is managed: controlled and uncontrolled. If the DOM handles the data, then the form is uncontrolled, and if the state of the form component manages the data, then the form is said to be controlled.

Here's an example of an uncontrolled form component.

      class UncontrolledForm extends React.Component {
  constructor() {
    this.nameInput = React.createRef();
  }

  submitFormHandler = (event) => {
    event.preventDefault();
    console.log(this.nameInput.current.value);
  };

  render() {
    return (
      <form onSubmit={this.submitFormHandler}>
        <div>
          <input type="text" name="name" ref={this.nameInput} />
        </div>
      </form>
    );
  }
}
    

Uncontrolled forms rely on the DOM to remember the form inputs and make use of ref to get the values from the inputs. The ref prop in the input tag will give you access to the value and other DOM properties of the input element. The downside of this approach is that you need to pull in the values from ref every time youo access them; this can be frustrating when you have multiple field values.

In a controlled form, the React component that renders the form is responsible for handling and managing the form values in the local state. That way, whenever the form value changes, it is immediately available to be accessed from the state and there's no need to pull the values using ref. This approach is considered more effective than using an uncontrolled form as you don't have to access the native input element in your component.

Take a look at the example below.

      class ControlledForm extends React.Component {
  constructor() {
    this.state = {
      values: {
        name: "",
      },
    };
  }

  submitFormHandler = (event) => {
    event.preventDefault();
    console.log(this.state.values);
  };

  inputChangeHandler = (event) => {
    this.setState({ values: { [event.target.name]: event.target.value } });
  };

  render() {
    const { values } = this.state;
    return (
      <form onSubmit={this.submitFormHandler}>
        <div>
          <input
            type="text"
            name="name"
            value={values.name}
            onChange={this.inputChangeHandler}
          />
        </div>
      </form>
    );
  }
}
    

As you can see in the code above, the input element has the value and onChange props attached to it. Whenever the input value changes, a change handler method is triggered that stores the value of the input in the component's state, and the value prop assigns the current value in the state to the input element. This way, the form value is immediately available inside the submit handler.

Error Handling

Now that you have an understanding of different forms in React, take a look at how to handle form errors in React.

Uncontrolled forms rely on native HTML5 input elements for validation, but native validation is not yet fully supported by some browsers and may lead to cross-browser compatibility issues. By contrast, in uncontrolled forms, error handling is done by the component state.

      class ControlledForm extends React.Component {
  constructor() {
    this.state = {
      values: {
        name: "",
      },
    };
  }

  submitFormHandler = (event) => {
    event.preventDefault();
    if (this.state.errors) return;
    console.log(this.state.values);
  };

  isValid = (input) => {
    if (input.value.trim().length === 0) {
      this.setState({ errors: { [input.name]: "This field is required" } });
    }
  };

  inputChangeHandler = (event) => {
    if (!this.isValid(event.target)) return;
    this.setState({ values: { [event.target.name]: event.target.value } });
  };

  render() {
    const { values, errors } = this.state;
    return (
      <form onSubmit={this.submitFormHandler}>
        <div>
          <input
            type="text"
            name="name"
            value={values.name}
            onChange={this.inputChangeHandler}
          />
          {errors.name && <div>{errors.name}</div>}
        </div>
      </form>
    );
  }
}
    

When working on real-world apps, you probably shouldn't handle forms from scratch; instead, use other third-party libraries like Formik or Redux-Forms. Using libraries will help you save a lot of time and provide you with an easy API to handle form values and validation.

How to Submit Form Values

Generally, you will submit form values inside the submit handler. In the example in the previous section, the form can be submitted using the submitFormHandler method.

To send form values to the backend service, you can either use the native fetch API or the axios HTTP library.

      import axios from "axios";

// ...
submitFormHandler = async (event) => {
  event.preventDefault();
  if (this.state.errors) return;
  const response = await axios.post(BACKEND_URL, {
    formData: this.state.values,
  });
  // do something after form submission
};
    

Sending form values is an asynchronous action, so make sure you use Promises or async/await syntax to handle the submission.

Conclusion

In this guide, you learned about the different types of forms in React and how to manage them. Controlled form inputs are preferred, as they encourage you to use the state to handle the values. But, as a developer, it is your job to choose the approach that best fits your app's use case.