How to Build Forms in React: A Guide for Frontend Developers

    Apr 1, 20249 min read1505 viewsUpdated:Nov 27, 2024
    How to Build Forms in React: A Guide for Frontend Developers

    Forms are an important part of web development for user interaction. In React, forms are built to manage the user inputs and states, there could be a complex structure of the form and it is important to master the form for frontend developers. This guide will teach you different ways to make forms in React, along with some tips for doing it well. By the end, you'll know how to make forms that work smoothly and are easy for users to use.

    building forms in react

    Table of Contents

    • Types of Forms

    • Types of Form Inputs

    • Controlled Forms

    • Uncontrolled Forms

    • Form Validations

    • React Form Styling

    • Form Libraries

    • Conclusion

    Types of Forms

    Contact Forms
    These are some of the most common types of forms on the web. They allow users to send a message directly to the website owner or administrator. They typically include fields for the user’s name, email address, subject, and message.

    Registration Forms
    These forms are used when a user wants to register for an account on a website. They usually ask for information like the user’s name, email address, and password. Some registration forms may also ask for additional information like a phone number or address.

    Login Forms
    These forms are used for users to log into their accounts. They typically have fields for an email address or username, and a password.

    Order Forms
    These forms are used on e-commerce websites to allow users to purchase products or services. They usually include fields for the user’s shipping and billing information, as well as details about the products or services being purchased.

    Feedback Forms
    These forms are used to collect feedback from users. They can be used to gather user opinions on various topics, such as the usability of a website or the quality of its content.

    Survey Forms
    These forms are used to collect data from users for research purposes. They can include a wide variety of question types, including multiple-choice, text response, and rating scales.

    Subscription Forms
    These forms are used to sign up users for regular updates or newsletters. They typically ask for the user’s email address, and possibly their name and other preferences.\

    Types of Form Inputs

    There are several types of form inputs that you can use. This depends on the kind of data you want to collect. Some of the form inputs are given below.

    Text Fields
    This common form element is used to collect single-line text input.

    Password Fields
    Similar to text fields but hides the text that the user types in.

    Radio Buttons
    This is a type of form component that allows the user to select one option from a set.

    Checkboxes
    These allow the user to select multiple options from a set.

    Select Menus
    These are drop-down lists that allow the user to select one option from a list.

    File Input
    These allow the user to select a file from their device to upload.

    Textareas
    These are used for multi-line text input.

    Buttons
    These are used to initiate form submission or other interactive features of the web application.

    Each of these form inputs has its own set of attributes that you can use to control their behavior and appearance. For example, you can use the placeholder attribute to display hint text in a text field, or the required attribute to make a field mandatory.

    Controlled Form in ReactJS

    Controlled components in React.js are components where the value of form elements is controlled by the React state ie. useState. When a user enters the value of the form, there is a method ‘onChange’ wherein it stores the value entered by the user is stored in the components state and updated by the setter function.

    import React, { useState } from 'react';
    
    const ControlledInput = () => {
      // State variable to hold the value of the input
      const [username, setUsername] = useState('');
    
      // Event handler to update the state when the input value changes
      const handleInputChange = (e) => {
        setUsername(e.target.value);
      };
    
      return (
        <div>
          {/* Input element with value bound to state variable and onChange event */}
          <input
            type="text"
            value={username}
            onChange={handleInputChange}
            placeholder="Enter your username"
          />
          {/* Display the value of the input */}
          <p>Username: {username}</p>
        </div>
      );
    };
    
    export default ControlledInput; 

    In this example:

    We initialize the username variable to store the value of the input field. The value attribute is for data binding the username state variable

    We define the onChange event to update the username state variable whenever the input value changes So, It provides a robust and flexible solution for managing elements in the react application.

    Uncontrolled Form in ReactJS

    Uncontrolled components in ReactJS are form elements where the value is handled by the web browser. So, in controlled components forms are handled by the state in React and are updated by the change function but in uncontrolled components, the browser handles the form value directly, we don’t need to manage the value through the React state.

    Here is an example of an uncontrolled input component in React:

    import React, { useRef } from 'react';
    
    const UncontrolledInput = () => {
      // Ref to access the input DOM node
      const inputRef = useRef(null);
    
      // Function to handle form submission
      const handleSubmit = (e) => {
        e.preventDefault();
        // Access input value using ref
        console.log('Input value:', inputRef.current.value);
      };
    
      return (
        <div>
          {/* Input element with defaultValue instead of value */}
          <input
            type="text"
            defaultValue="Initial Value"
            ref={inputRef} // Assign ref to input element
            placeholder="Enter text"
          />
          {/* Button to submit form */}
          <button onClick={handleSubmit}>Submit</button>
        </div>
      );
    };
    
    export default UncontrolledInput;

    We create a ref ‘inputRef’ using the useRef() hook to get access to the input dom node directly.When the form is submitted, we get the value of the form by using  ‘inputRef.current.value’

    Here, we didn’t use the state and onChange function we directly targeted the ref and got the value of the form. Uncontrolled components are feasible for building lightweight forms in react application, but for complex forms controlled component is the best choice.

    Form Validation

    Form validation in React.js means ensuring the information users enter into a form meets certain rules before it's sent to a server or used for anything else.

    React provides various approaches to handle form validation, including manual validation, using libraries like Formik or React Hook Form, or HTML5 form validation attributes.
    Form validation in React.js involves the user input meeting specific criteria before it's submitted to a server or processed further. React provides various methods to handle form validation, including manual validation, using libraries like Formik or React Hook Form, or employing native HTML5 form validation attributes. Let's explore these methods:

    Manual Validation

    • In manual validation, we define custom validation logic by handling form submissions and input changes.

    • You can use the state to store form data and validation errors and update them based on user input.

      Let's have an example

      const [formData, setFormData] = useState({
        username: '',
        password: '',
      });
      
      const [errors, setErrors] = useState({});
      
      const validateForm = () => {
        const errors = {};
      
        if (!formData.username.trim()) {
          errors.username = 'Username is required';
        }
      
        if (!formData.password.trim()) {
          errors.password = 'Password is required';
        }
      
        setErrors(errors);
        return Object.keys(errors).length === 0;
      };
      
      const handleSubmit = (e) => {
        e.preventDefault();
        if (validateForm()) {
          // Form submission logic
        }
      };
      
      const handleInputChange = (e) => {
        const { name, value } = e.target;
        setFormData((prevData) => ({
          ...prevData,
          [name]: value,
        }));
      };
      
      return (
        <form onSubmit={handleSubmit}>
          <input
            type="text"
            name="username"
            value={formData.username}
            onChange={handleInputChange}
          />
          {errors.username && <p>{errors.username}</p>}
          <input
            type="password"
            name="password"
            value={formData.password}
            onChange={handleInputChange}
          />
          {errors.password && <p>{errors.password}</p>}
          <button type="submit">Submit</button>
        </form>
      );

    Here, we created a custom function for validation where we call this function on the submit button, it checks whether the user has entered the correct text values or not, based on user inputs it will throw an error or will submit the full. For simple form it is helpful we create an error state object whenever any user enters the wrong value it will add values to the error state object and will display the error to the user. After filling the form correctly then the form will be submitted.

    Using Formik

    By using libraries things get easier we don't write the custom error message, In Formik we have validationSchema provided by Formik wherein we check the validation of input fields.

    Let's take an example,

    import { Formik, Form, Field, ErrorMessage } from 'formik';
    import * as Yup from 'yup';
    
    const validationSchema = Yup.object({
      username: Yup.string().required('Username is required'),
      password: Yup.string().required('Password is required'),
    });
    
    const MyForm = () => (
      <Formik
        initialValues={{ username: '', password: '' }}
        validationSchema={validationSchema}
        onSubmit={(values) => {
          // Form submission logic
        }}
      >
        <Form>
          <Field type="text" name="username" />
          <ErrorMessage name="username" component="div" />
          <Field type="password" name="password" />
          <ErrorMessage name="password" component="div" />
          <button type="submit">Submit</button>
        </Form>
      </Formik>
    );
    

    In the above code,

    Formik, Field, and ErrorMessage are components provided by the Formik library for building forms in React. Yup is a validation library used to define validation schemas for form fields.ValidationSchema is defined using Yup's method to create a schema for the form fields. In this example, the schema specifies that the username and password fields are required, and if the validation fails, it provides a corresponding error message. The field component is used to render the user's input elements each of the properties has attributes like type and name fields. The Error message is used to display the errors associated with the user's input elements.

    Overall, this code sets up a basic form with validation using Formik and Yup in React. It provides a structured way to manage form state, handle form validation, and submit form data.

    Using HTML5 Form Validation errors

    HTML5 form validation attributes provide a straightforward way to validate form inputs directly in the browser without needing to write custom JavaScript code. We can add these attributes to your HTML form elements to enforce basic validation rules, such as requiring a field to be filled, restricting the input pattern, or setting minimum and maximum lengths.

    • required: This attribute ensures that the field must be filled out before the form can be submitted.

    <input type="text" name="username" required />
    • pattern: With the pattern attribute, you can specify a regular expression that the input value must match. It's useful for specific formats like email addresses or phone numbers.

    <input type="text" name="email" pattern="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" />
    • minLength and maxLength: These attributes define the minimum and maximum length of the input value, respectively.

    <input type="text" name="password" minLength="6" maxLength="20" />

    By using these commands we can check the validation using HTML5. we can provide error messages to users when they fill out forms incorrectly.

    React Form Styling

    Styling forms in React can be approached in various ways, depending on your preferences and project requirements

    CSS Frameworks

    CSS frameworks like Bootstrap, and Material-UI give you ready-made styles and components for forms. They make it easy to style forms quickly and keep the look consistent.

    Example of CSS Frameworks

    import 'bootstrap/dist/css/bootstrap.min.css';
    
    const MyForm = () => (
      <form>
        <div className="mb-3">
          <label htmlFor="exampleFormControlInput1" className="form-label">Email address</label>
          <input type="email" className="form-control" id="exampleFormControlInput1" placeholder="name@example.com" />
        </div>
        <button type="submit" className="btn btn-primary">Submit</button>
      </form>
    );

    Utility Classes

    With frameworks like Tailwind CSS, we can style elements in your JSX directly by using utility classes. Here, we don't have to create custom CSS for every element.

    Utility classes offer a fast way to make sure our components look the same across our project, without having to write a lot of CSS code.

    Example of Utility Class

    const MyForm = () => (
      <form className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
        <div className="mb-4">
          <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="username">
            Username
          </label>
          <input className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="username" type="text" placeholder="Username" />
        </div>
        <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" type="submit">
          Submit
        </button>
      </form>
    );

    Custom CSS

    We can also use custom CSS files to style your forms by following traditional CSS practices. Create CSS files containing styles for our forms and import them into your React components.

    import './MyForm.css';
    
    const MyForm = () => (
      <form className="my-form">
        <input type="text" className="input-field" />
        <button type="submit" className="submit-button">Submit</button>
      </form>
    );

    Form Libraries

    Form libraries like Formik, and ReactHookForm offer pre-built components for managing the form state. These libraries add good advanced features for handling complex forms.
    Let's learn how to implement Formik,

    Formik

    import React from 'react';
    import { Formik, Form, Field, ErrorMessage } from 'formik';
    
    const MyForm = () => (
      <Formik
        initialValues={{ email: '', password: '' }}
        validate={values => {
          const errors = {};
          if (!values.email) {
            errors.email = 'Required';
          } else if (!isValidEmail(values.email)) {
            errors.email = 'Invalid email address';
          }
          return errors;
        }}
        onSubmit={(values, { setSubmitting }) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 400);
        }}
      >
        {({ isSubmitting }) => (
          <Form>
            <Field type="email" name="email" />
            <ErrorMessage name="email" component="div" />
            <Field type="password" name="password" />
            <ErrorMessage name="password" component="div" />
            <button type="submit" disabled={isSubmitting}>
              Submit
            </button>
          </Form>
        )}
      </Formik>
    );
    
    export default MyForm;

    So, we imported the components such as Form, Field, and ErrorMessage from Formik. The MyForm components contain the logic of forms. Within the Formik wrappers, we initialize the form with initial values for the email and password fields. A validation function is specified so necessary validation is provided if the user entered the wrong email and password. When the form is submitted the onSubmit function will handle the data from the form. Overall the structure is maintained where the developers will write and maintain the code easier and user experience will be enhanced.

    Form libraries like Formik are tools that help React developers deal with forms in their applications. Imagine you're building a website where users need to fill out forms—like signing up, logging in, or submitting feedback. Handling these forms can get messy with lots of code to manage things like checking if inputs are filled out correctly and sending the data to the server.

    Formik makes this easier by providing a set of tools to manage forms efficiently. It helps you define forms, handle when users type into them, check that the information is correct, and submit it securely. Think of it like having a helper that takes care of the annoying parts of forms, so you can focus on making your website awesome.

    With Formik, you write less code and keep your forms organized, making your life as a developer simpler and your users happier.

    React-Hook=Form

    Another way for form handling is done by react-hook-form. It makes the form management easy and fast.

    Let's consider a simple form for collecting user information, including name and email address.

    import React from 'react';
    import { useForm } from 'react-hook-form';
    
    function MyForm() {
      const { register, handleSubmit, errors } = useForm();
    
      const onSubmit = (data) => {
        console.log(data);
      };
    
      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <input type="text" name="name" placeholder="Name" ref={register({ required: true })} />
          {errors.name && <span>Name is required</span>}
          
          <input type="email" name="email" placeholder="Email" ref={register({ required: true, pattern: /^\S+@\S+$/i })} />
          {errors.email && <span>Invalid email address</span>}
          
          <button type="submit">Submit</button>
        </form>
      );
    }
    
    export default MyForm;
    

    Here we imported the useForm hook from react-hook-form. The register function is used to register input fields from the form. It enables validation and access to the value

    handleSubmit function is called on form submission to trigger form validation and handles the form submission.

    errors object contains errors in each field in the form.

    This is how react-hook-form works.

    React Hook Form is a great tool for handling forms in React apps. It keeps things simple and easy for developers by providing a straightforward way to manage form stuff without a lot of extra complexity. With React Hook Form, you can spend more time making your app awesome for users and less time worrying about all the tricky parts of forms, like keeping track of what people type and making sure it's correct. It's like having a helpful assistant who takes care of all the boring stuff so you can focus on making your app amazing.

    Conclusion

    Learning how to build forms in React is very important. It involves understanding controlled components and uncontrolled components, and how they work, are stored, and are maintained in a React component. Validation plays an important role in entering the right information, So it is important to do validation wherever it is required. Form libraries are also useful as they provide predefined functionalities to make development easier and faster.

    Having good knowledge in building forms in ReactJS helps developers to make forms that will work well and are easy for users to use. So, knowing the form is useful for the developers. This is important for creating modern web applications that meet the needs of different users.

    24

    Related articles

    This website uses cookies to analyze website traffic and optimize your website experience. By continuing, you agree to our use of cookies as described in our Privacy Policy.