← Back to Chapters

Handling Input, Textarea & Select in React

⚛️ Handling Input, Textarea & Select in React

React Forms · Controlled Components

⚡ Quick Overview

React handles all common form elements — input, textarea, and select — in a consistent, predictable way using state and the onChange handler.

Each element represents user input differently, but the core idea is the same: the UI reflects the state, and the state updates as the user types or selects options.

? Key Concepts

  • Controlled components: form elements whose value is always driven by React state.
  • value + onChange pair: React reads from state using value and writes back using onChange.
  • textarea in React uses a value prop instead of inner text.
  • select uses a single value on the <select> tag to track the selected option.
  • Each input should have a name attribute for easier, dynamic state updates.

? Syntax / Theory

Common pattern for any controlled form element in React:

  • Declare state using useState (or part of a bigger form object).
  • Bind the element’s value to that state.
  • Update state on every onChange event.

Generic pattern:

  • const [value, setValue] = useState("");
  • <input value={value} onChange={(e) => setValue(e.target.value)} />

This pattern is reused for input, textarea, and select — only the element type and UI change, not the state logic.

? Code Example(s)

? Handling Text Input

Text inputs are controlled by linking the value prop to a state variable and updating it via onChange.

? View Code Example – Input
// Controlled text input using React state
import React, { useState } from "react";

function InputExample() {
  const [name, setName] = useState("");

  const handleChange = (e) => setName(e.target.value);

  return (
    <div>
      <h4>Input Example</h4>
      <input
        type="text"
        className="form-control"
        placeholder="Enter your name"
        value={name}
        onChange={handleChange}
      />
      <p className="mt-2">Hello, {name || "Guest"}!</p>
    </div>
  );
}

export default InputExample;

? Handling Textarea

In plain HTML, the content of a textarea goes between <textarea>...</textarea>. In React, textarea behaves just like an input: its content is controlled through the value prop.

? View Code Example – Textarea
// Controlled textarea that tracks message length
import React from "react";

function TextareaExample() {
  const [message, setMessage] = React.useState("");

  const handleChange = (e) => setMessage(e.target.value);

  return (
    <div>
      <h4>Textarea Example</h4>
      <textarea
        className="form-control"
        rows="3"
        placeholder="Type your feedback..."
        value={message}
        onChange={handleChange}
      />
      <p className="mt-2 text-muted">
        {message.length}/200 characters typed
      </p>
    </div>
  );
}

export default TextareaExample;

? Handling Select Dropdown

The select element uses a value prop to track the selected option. Changing it updates the associated state and triggers a re-render.

? View Code Example – Select
// Controlled select dropdown for choosing a country
import React from "react";

function SelectExample() {
  const [country, setCountry] = React.useState("India");

  const handleChange = (e) => setCountry(e.target.value);

  return (
    <div>
      <h4>Select Dropdown Example</h4>
      <select
        className="form-select"
        value={country}
        onChange={handleChange}
      >
        <option value="India">India</option>
        <option value="USA">USA</option>
        <option value="Germany">Germany</option>
        <option value="Japan">Japan</option>
      </select>
      <p className="mt-2">You selected: {country}</p>
    </div>
  );
}

export default SelectExample;

⚙️ Combined Feedback Form

You can combine input, textarea, and select elements in a single controlled form by storing them in one state object.

? View Code Example – Combined Form
// Single form state object for input, textarea, and select
import React from "react";

function FeedbackForm() {
  const [form, setForm] = React.useState({
    name: "",
    feedback: "",
    rating: "Good",
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm((prevForm) => ({
      ...prevForm,
      [name]: value,
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault(); // Stop page reload on submit
    alert(JSON.stringify(form, null, 2));
  };

  return (
    <form onSubmit={handleSubmit}>
      <div className="mb-3">
        <label>Name</label>
        <input
          type="text"
          name="name"
          className="form-control"
          placeholder="Enter your name"
          value={form.name}
          onChange={handleChange}
        />
      </div>

      <div className="mb-3">
        <label>Feedback</label>
        <textarea
          name="feedback"
          className="form-control"
          rows="3"
          placeholder="Write your feedback..."
          value={form.feedback}
          onChange={handleChange}
        />
      </div>

      <div className="mb-3">
        <label>Rating</label>
        <select
          name="rating"
          className="form-select"
          value={form.rating}
          onChange={handleChange}
        >
          <option>Excellent</option>
          <option>Good</option>
          <option>Average</option>
          <option>Poor</option>
        </select>
      </div>

      <button className="btn btn-primary">Submit Feedback</button>
    </form>
  );
}

export default FeedbackForm;

? Live Output / Explanation

What Happens When the User Interacts?

  • In InputExample, every keystroke in the text box fires onChange, updates name, and re-renders the greeting: Hello, <name>!.
  • In TextareaExample, typing into the textarea updates message. The paragraph below shows a live character count using message.length.
  • In SelectExample, choosing a different country updates country and the text You selected: ... reflects the new value.
  • In FeedbackForm, all fields write into one form object. On submit, the form is prevented from reloading the page using e.preventDefault(), and the final data is shown via alert(JSON.stringify(form, null, 2)).

In all cases, state is the single source of truth for what appears in every form control.

? Tips & Best Practices

  • Initialize all form fields in the component’s state to avoid “uncontrolled component” warnings.
  • Use a single handleChange function for multiple fields by relying on e.target.name and dynamic keys: [name].
  • Use defaultValue when you only need an initial value and do not need the field to be fully controlled.
  • Always call e.preventDefault() in onSubmit handlers to prevent full page reloads for React forms.
  • Keep form state as small and flat as possible; store only what you actually need (e.g., no derived values).

? Try It Yourself / Practice Tasks

  1. Create a feedback form that includes an input, textarea, and select field.
  2. Display a live preview of all values (name, feedback, rating) as the user types or selects.
  3. Add a character limit counter for the textarea (for example, 0/200 characters).
  4. Show a custom thank-you message under the form after successful submission.

Goal: Master handling text, textarea, and select fields in React using state and unified change handlers for clean and controlled form management.