Handling Multiple Inputs

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

Handling Multiple Inputs

When building a controlled form with multiple inputs, the naïve approach is to create a separate useState Hook and a separate onChange handler for every single input.

// ❌ The Tedious Way
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');

const handleFirstName = (e) => setFirstName(e.target.value);
const handleLastName = (e) => setLastName(e.target.value);
const handleEmail = (e) => setEmail(e.target.value);

For a form with two inputs, this is fine. For a form with ten inputs, this becomes a nightmare to manage.

The Single State Object Pattern

To handle multiple inputs cleanly, you should use a single state object to hold all the form data, and a single, unified handleChange function.

How it works

  1. Define a single useState object where the keys match the name attributes of your HTML inputs.
  2. Give every <input> a name attribute.
  3. Write one handleChange function that uses the event.target.name to figure out which part of the state object to update.
import { useState } from 'react';

function MultiInputForm() {
  // 1. Single state object
  const [formData, setFormData] = useState({
    firstName: '',
    lastName: '',
    email: ''
  });

  // 2. Unified change handler
  const handleChange = (event) => {
    const { name, value } = event.target;
    
    setFormData(prevData => ({
      ...prevData,      // Copy all existing data
      [name]: value     // Overwrite only the specific field that changed
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    console.log("Submitting:", formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="text" 
        name="firstName" // MUST match the state key
        value={formData.firstName} 
        onChange={handleChange} 
      />
      <input 
        type="text" 
        name="lastName"  // MUST match the state key
        value={formData.lastName} 
        onChange={handleChange} 
      />
      <input 
        type="email" 
        name="email"     // MUST match the state key
        value={formData.email} 
        onChange={handleChange} 
      />
      <button type="submit">Submit</button>
    </form>
  );
}

Handling Checkboxes

Checkboxes are a slight exception. Instead of reading event.target.value, you need to read event.target.checked. You can easily adapt the unified handler to support both text inputs and checkboxes.

  const handleChange = (event) => {
    const { name, value, type, checked } = event.target;
    
    // Determine the correct value based on the input type
    const newValue = type === 'checkbox' ? checked : value;
    
    setFormData(prevData => ({
      ...prevData,
      [name]: newValue
    }));
  };

Interview Questions

Q: How can you handle 10 different text inputs in a form without writing 10 different state variables and 10 different onChange functions?
A: Store the form data as a single state object. Give every input a name attribute matching the object keys, and use a single dynamic onChange handler:

setFormData(prev => ({ ...prev, [e.target.name]: e.target.value }))