In this section, we will explore how to handle forms in React using controlled components. Forms are a crucial part of web applications, allowing users to input and submit data. Controlled components provide a way to manage form data within the React component state, ensuring that the UI and state are always in sync.

Key Concepts

  1. Controlled Components: Components where the form data is handled by the React component state.
  2. Uncontrolled Components: Components where the form data is handled by the DOM itself.
  3. Handling Form Submission: Managing the form submission event to process the input data.
  4. Form Validation: Ensuring that the input data meets certain criteria before submission.

Controlled Components

In a controlled component, the form data is managed by the state of the React component. This means that the input elements' values are bound to the state, and any changes to the input elements update the state.

Example: Controlled Input

import React, { useState } from 'react';

function ControlledInput() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`Submitted value: ${inputValue}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Input:
        <input type="text" value={inputValue} onChange={handleChange} />
      </label>
      <button type="submit">Submit</button>
    </form>
  );
}

export default ControlledInput;

Explanation

  • State Management: The useState hook is used to create a state variable inputValue and a function setInputValue to update it.
  • Event Handling: The handleChange function updates the state whenever the input value changes.
  • Form Submission: The handleSubmit function prevents the default form submission behavior and displays an alert with the submitted value.

Handling Multiple Inputs

When dealing with multiple input fields, you can manage them using a single state object.

Example: Multiple Controlled Inputs

import React, { useState } from 'react';

function MultipleInputs() {
  const [formData, setFormData] = useState({
    firstName: '',
    lastName: '',
    email: ''
  });

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

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`Submitted data: ${JSON.stringify(formData)}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        First Name:
        <input type="text" name="firstName" value={formData.firstName} onChange={handleChange} />
      </label>
      <br />
      <label>
        Last Name:
        <input type="text" name="lastName" value={formData.lastName} onChange={handleChange} />
      </label>
      <br />
      <label>
        Email:
        <input type="email" name="email" value={formData.email} onChange={handleChange} />
      </label>
      <br />
      <button type="submit">Submit</button>
    </form>
  );
}

export default MultipleInputs;

Explanation

  • State Object: The formData state object holds the values of multiple input fields.
  • Dynamic Handling: The handleChange function dynamically updates the state based on the input field's name attribute.

Form Validation

Form validation ensures that the input data meets certain criteria before submission.

Example: Form Validation

import React, { useState } from 'react';

function FormWithValidation() {
  const [formData, setFormData] = useState({
    username: '',
    password: ''
  });
  const [errors, setErrors] = useState({});

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

  const validate = () => {
    const newErrors = {};
    if (!formData.username) newErrors.username = 'Username is required';
    if (!formData.password) newErrors.password = 'Password is required';
    return newErrors;
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    const validationErrors = validate();
    if (Object.keys(validationErrors).length > 0) {
      setErrors(validationErrors);
    } else {
      alert(`Submitted data: ${JSON.stringify(formData)}`);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Username:
        <input type="text" name="username" value={formData.username} onChange={handleChange} />
        {errors.username && <span style={{ color: 'red' }}>{errors.username}</span>}
      </label>
      <br />
      <label>
        Password:
        <input type="password" name="password" value={formData.password} onChange={handleChange} />
        {errors.password && <span style={{ color: 'red' }}>{errors.password}</span>}
      </label>
      <br />
      <button type="submit">Submit</button>
    </form>
  );
}

export default FormWithValidation;

Explanation

  • Validation Function: The validate function checks for empty fields and returns an object with error messages.
  • Error Handling: The handleSubmit function sets the errors state if validation fails, displaying error messages next to the respective input fields.

Practical Exercise

Exercise: Create a Controlled Form

Create a controlled form with the following fields:

  • Name
  • Email
  • Password

Implement form validation to ensure that all fields are filled out before submission.

Solution

import React, { useState } from 'react';

function ControlledForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    password: ''
  });
  const [errors, setErrors] = useState({});

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

  const validate = () => {
    const newErrors = {};
    if (!formData.name) newErrors.name = 'Name is required';
    if (!formData.email) newErrors.email = 'Email is required';
    if (!formData.password) newErrors.password = 'Password is required';
    return newErrors;
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    const validationErrors = validate();
    if (Object.keys(validationErrors).length > 0) {
      setErrors(validationErrors);
    } else {
      alert(`Submitted data: ${JSON.stringify(formData)}`);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input type="text" name="name" value={formData.name} onChange={handleChange} />
        {errors.name && <span style={{ color: 'red' }}>{errors.name}</span>}
      </label>
      <br />
      <label>
        Email:
        <input type="email" name="email" value={formData.email} onChange={handleChange} />
        {errors.email && <span style={{ color: 'red' }}>{errors.email}</span>}
      </label>
      <br />
      <label>
        Password:
        <input type="password" name="password" value={formData.password} onChange={handleChange} />
        {errors.password && <span style={{ color: 'red' }}>{errors.password}</span>}
      </label>
      <br />
      <button type="submit">Submit</button>
    </form>
  );
}

export default ControlledForm;

Explanation

  • State Management: The formData state object holds the values of the form fields.
  • Validation: The validate function checks for empty fields and sets error messages.
  • Error Display: Error messages are displayed next to the respective input fields if validation fails.

Conclusion

In this section, we learned how to handle forms in React using controlled components. We covered the basics of controlled components, handling multiple inputs, form validation, and provided practical examples and exercises. Understanding controlled components is essential for managing form data effectively in React applications. In the next module, we will dive into more advanced component concepts, including lifting state up and composition vs inheritance.

React Course

Module 1: Introduction to React

Module 2: React Components

Module 3: Working with Events

Module 4: Advanced Component Concepts

Module 5: React Hooks

Module 6: Routing in React

Module 7: State Management

Module 8: Performance Optimization

Module 9: Testing in React

Module 10: Advanced Topics

Module 11: Project: Building a Complete Application

© Copyright 2024. All rights reserved