React useState and how to use them in Forms

Harsh Mishra - Sep 27 - - Dev Community

Understanding useState in React

React is a powerful library for building user interfaces, and one of its most important features is the ability to manage state. In function components, state management is typically done using the useState hook. In this section, we’ll dive into what useState is, how to use it, and provide a complete example of a counter app built with React.

What is useState?

useState is a Hook that lets you add React state to function components. It allows you to store and update values that can change over time. When the state changes, React re-renders the component to reflect the updated state.

Syntax of useState

The useState hook is simple to use. It takes one argument, the initial state, and returns an array containing two elements:

  1. The current state value: This is the current value of the state.
  2. A function to update the state: This function is used to update the state value whenever necessary.

Here is the basic syntax:

const [state, setState] = useState(initialState);
Enter fullscreen mode Exit fullscreen mode
  • state: The current state value.
  • setState: The function to update the state.
  • initialState: The initial value of the state. This can be any data type—string, number, array, object, etc.

Detailed Explanation

  • Initial State: The initial state can be any valid JavaScript value. This value will be assigned to the state variable when the component is first rendered.

  • State Variable: The first element in the array returned by useState is the current state value. This value is read-only, meaning you should not modify it directly. Instead, use the state setter function.

  • State Setter Function: The second element is a function that allows you to update the state. When you call this function with a new value, React schedules a re-render of the component with the updated state.

Example: Counter App Using useState

Let’s walk through a simple example to demonstrate how useState works. We’ll create a counter app where you can increase and decrease a number by clicking buttons.

import React, { useState } from 'react';

function Counter() {
  // Declare a state variable 'count' initialized to 0
  const [count, setCount] = useState(0);

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h1>Counter: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increase</button>
      <button onClick={() => setCount(count - 1)}>Decrease</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}

export default Counter;
Enter fullscreen mode Exit fullscreen mode

React counter app output

Breakdown of the Code:
  1. Importing useState: We import useState from React to use it in our component.

  2. Declaring State:

   const [count, setCount] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Here, we declare a state variable count and initialize it with 0. We also get a function setCount to update the count value.

  1. Rendering the UI:

    • We display the current count value inside an <h1> tag.
    • We provide three buttons:
      • Increase: Increases the count by 1.
      • Decrease: Decreases the count by 1.
      • Reset: Resets the count to 0.
  2. Updating State:

    • The onClick event handlers for the buttons call setCount with the appropriate value to update the state.
    • When setCount is called, React triggers a re-render, and the updated count value is reflected in the UI.

The useState hook is essential for managing state in React function components. It’s straightforward to use and allows for dynamic and responsive user interfaces. By understanding how useState works, you can create more interactive and functional components.

In the next section, we’ll explore how to use React forms and manage their state effectively using useState.

Making Forms in React

Forms are fundamental to web applications, enabling users to input and submit data. React simplifies form handling by managing form data through state, allowing for dynamic and interactive user interfaces. In this guide, we’ll explore how to build and handle forms in React, covering a wide range of HTML form elements and advanced features.

Controlled Components in React Forms

In React, forms are typically implemented as controlled components. A controlled component is one where form data is managed by the React component’s state. This ensures that the form inputs remain synchronized with the state, providing a clear and predictable flow of data.

Key Concepts
  1. State Management: Form input values are stored in the component's state using the useState hook.
  2. Binding Inputs: Form inputs are controlled by binding their value attribute to state variables.
  3. Handling Events: The onChange event handler is used to update state as the user interacts with the form.
  4. Form Submission: The onSubmit event handler processes form data, often preventing the default behavior to handle submission with JavaScript.

Example: Comprehensive Real-World Form

Let’s build a comprehensive form example that includes a wide variety of HTML form elements: text, password, email, number, radio, checkbox, select dropdown, textarea, color picker, date picker, range slider, time picker, and more. This form will store the data in the component’s state and display the submitted data.

import React, { useState } from 'react';

function ComprehensiveForm() {
  // State for all form inputs
  const [formData, setFormData] = useState({
    name: '',
    password: '',
    email: '',
    phone: '',
    age: '',
    gender: '',
    hobbies: [],
    color: '',
    dateOfBirth: '',
    appointmentTime: '',
    favoriteMonth: '',
    rangeValue: 50,
    comments: '',
    termsAccepted: false
  });

  // Handle input change
  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;

    if (type === 'checkbox') {
      if (name === 'hobbies') {
        setFormData((prevData) => ({
          ...prevData,
          hobbies: checked 
            ? [...prevData.hobbies, value] 
            : prevData.hobbies.filter(hobby => hobby !== value)
        }));
      } else {
        setFormData((prevData) => ({
          ...prevData,
          [name]: checked
        }));
      }
    } else {
      setFormData((prevData) => ({
        ...prevData,
        [name]: value
      }));
    }
  };

  // Handle form submission
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form Data:', formData);
    // You can also send formData to an API or perform other actions here
  };

  return (
    <div style={{ padding: '20px' }}>
      <h2>Comprehensive React Form Example</h2>
      <form onSubmit={handleSubmit}>

        {/* Name Input */}
        <fieldset>
          <legend>Personal Information</legend>
          <div>
            <label>Name:</label>
            <input 
              type="text" 
              name="name" 
              value={formData.name} 
              onChange={handleChange} 
              required 
            />
          </div>

          {/* Password Input */}
          <div>
            <label>Password:</label>
            <input 
              type="password" 
              name="password" 
              value={formData.password} 
              onChange={handleChange} 
              required 
            />
          </div>

          {/* Email Input */}
          <div>
            <label>Email:</label>
            <input 
              type="email" 
              name="email" 
              value={formData.email} 
              onChange={handleChange} 
              required 
            />
          </div>

          {/* Phone Number Input */}
          <div>
            <label>Phone Number:</label>
            <input 
              type="tel" 
              name="phone" 
              value={formData.phone} 
              onChange={handleChange} 
              required 
            />
          </div>

          {/* Number Input */}
          <div>
            <label>Age:</label>
            <input 
              type="number" 
              name="age" 
              value={formData.age} 
              onChange={handleChange} 
              required 
            />
          </div>
        </fieldset>

        {/* Gender Radio Inputs */}
        <fieldset>
          <legend>Gender</legend>
          <div>
            <input 
              type="radio" 
              name="gender" 
              value="Male" 
              checked={formData.gender === 'Male'} 
              onChange={handleChange} 
            /> Male
            <input 
              type="radio" 
              name="gender" 
              value="Female" 
              checked={formData.gender === 'Female'} 
              onChange={handleChange} 
            /> Female
            <input 
              type="radio" 
              name="gender" 
              value="Other" 
              checked={formData.gender === 'Other'} 
              onChange={handleChange} 
            /> Other
          </div>
        </fieldset>

        {/* Hobbies Checkbox Inputs */}
        <fieldset>
          <legend>Hobbies</legend>
          <div>
            <label>
              <input 
                type="checkbox" 
                name="hobbies" 
                value="Reading" 
                checked={formData.hobbies.includes('Reading')} 
                onChange={handleChange} 
              /> Reading
            </label>
            <label>
              <input 
                type="checkbox" 
                name="hobbies" 
                value="Traveling" 
                checked={formData.hobbies.includes('Traveling')} 
                onChange={handleChange} 
              /> Traveling
            </label>
            <label>
              <input 
                type="checkbox" 
                name="hobbies" 
                value="Gaming" 
                checked={formData.hobbies.includes('Gaming')} 
                onChange={handleChange} 
              /> Gaming
            </label>
            <label>
              <input 
                type="checkbox" 
                name="hobbies" 
                value="Cooking" 
                checked={formData.hobbies.includes('Cooking')} 
                onChange={handleChange} 
              /> Cooking
            </label>
          </div>
        </fieldset>

        {/* Favorite Color Input */}
        <fieldset>
          <legend>Preferences</legend>
          <div>
            <label>Favorite Color:</label>
            <input 
              type="color" 
              name="color" 
              value={formData.color} 
              onChange={handleChange} 
            />
          </div>

          {/* Date Picker Input */}
          <div>
            <label>Date of Birth:</label>
            <input 
              type="date" 
              name="dateOfBirth" 
              value={formData.dateOfBirth} 
              onChange={handleChange} 
              required 
            />
          </div>

          {/* Time Picker Input */}
          <div>
            <label>Appointment Time:</label>
            <input 
              type="time" 
              name="appointmentTime" 
              value={formData.appointmentTime} 
              onChange={handleChange} 
            />
          </div>

          {/* Month Picker Input */}
          <div>
            <label>Favorite Month:</label>
            <input 
              type="month" 
              name="favoriteMonth" 
              value={formData.favoriteMonth} 
              onChange={handleChange} 
            />
          </div>

          {/* Range Slider Input */}
          <div>
            <label>Range Value ({formData.rangeValue}):</label>
            <input 
              type="range" 
              name="rangeValue" 
              min="0" 
              max="100" 
              value={formData.rangeValue} 
              onChange={handleChange} 
            />
          </div>
        </fieldset>

        {/* Textarea Input */}
        <fieldset>
          <legend>Additional Information</legend>
          <div>
            <label>Comments:</label>
            <textarea 
              name="comments" 
              value={formData.comments} 
              onChange={handleChange} 
            />
          </div>
        </fieldset>

        {/* Terms and Conditions Checkbox */}
        <fieldset>
          <legend>Terms and Conditions</legend>
          <div>
            <label>
              <input 
                type="checkbox" 
                name="termsAccepted" 
                checked={formData.termsAccepted} 
                onChange={handleChange} 
                required 
              /> I accept the terms and conditions
            </label>
          </div>
        </fieldset>

        {/* Submit Button */}
        <div>
          <button type="submit">Submit</button>
        </div>
      </form>

      {/* Display Submitted Data */}
      <div style={{ marginTop: '20px' }}>
        <h3>Submitted Data:</h3>
        <pre>{JSON.stringify(formData, null, 2)}</pre>
      </div>
    </div>
  );
}

export default ComprehensiveForm;
Enter fullscreen mode Exit fullscreen mode

React Form demo output

Breakdown of the Code:
  1. State Initialization:

    • We initialize the formData state using useState, with properties for each form input. For example, name for the name input, email for the email input, etc. Arrays are used for checkboxes (hobbies), and booleans for single checkboxes (termsAccepted).
  2. Handling Input Changes:

    • The handleChange function updates the state based on user input. For checkboxes, it handles both single and multiple values (like the hobbies array). The checked attribute is used for checkbox and radio inputs to determine if the input is selected.
  3. Handling Form Submission:

    • The handleSubmit function prevents the default form submission behavior and logs the form data to the console. This function could be adapted to send the form data to an API.
  4. Rendering the Form:

    • Various input elements are created, such as text, password, email, number, radio buttons, checkboxes, color picker, date picker, range slider, and more. Each input is bound to the corresponding state value using the value or checked attribute, and the onChange event updates the state accordingly.
    • The form is organized into logical sections using <fieldset> and <legend> to group related inputs, improving readability and accessibility.
    • The form data is displayed below the form after submission, formatted as JSON.

Summary

This comprehensive example demonstrates how to build a real-world form in React using a wide variety of HTML elements. By managing form inputs as controlled components through React state, you gain full control over user input, making it easier to handle form validation, submission, and data management. This approach is essential for building complex forms in modern web applications.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .