DEV Community

Debora Galeano
Debora Galeano

Posted on

How to handle multiple inputs in React

I recently had to refactor a React Form when working with multiple inputs and I thought I'd share how I did it.

This is how my form looks like:

Screen Shot 2020-11-28 at 10.38.42 PM

The Problem

  • Look at the starter code below
  • This Form component has 5 input fields in total; 5 different states and 5 different onChange inline functions
  • This is not exactly DRY code 🙀


import React, { useState } from "react";

export default function Form() {
  const [newCompany, setCompany] = useState("");
  const [newPosition, setPosition] = useState("");
  const [newLink, setNewLink] = useState("");
  const [newDate, setNewDate] = useState("");
  const [newNote, setNewNote] = useState("");

  return (
        <form>
          <input
            value={newCompany}
            onChange={(e) => setCompany(e.target.value)}
            label="Company"
          />
          <input
            value={newPosition}
            onChange={(e) => setPosition(e.target.value)}
            label="Job Title"
          />
          <input
            value={newLink}
            onChange={(e) => setNewLink(e.target.value)}
            label="Job Link"
          />
          <input
            type="date"
            value={newDate}
            onChange={(e) => setNewDate(e.target.value)}
          />
          <input
            value={newNote}
            onChange={(e) => setNewNote(e.target.value)}
            label="Note"
          />
          <button type="submit"> Submit </button>
        </form>
  );
}


Enter fullscreen mode Exit fullscreen mode
  • Also, if I want to add a reset function later, my code will look like this: 🙅🏽‍♀️


  const reset = () => {
    setCompany("");
    setPosition("");
    setNewLink("");
    setNewDate("");
    setNewNote("");
  };


Enter fullscreen mode Exit fullscreen mode

The Solution: Refactoring ✨

Step 1: Add input default values and initialize state

  • First, let's add default values to ALL input fields
  • How do we do that? We create an object literal with those values and set to empty string
  • Then, with the useState() React Hook we initialize our values state with the initialValues object
  • Important: Remember to add the value attribute to every input field with its corresponding value (e.g. values={values.company})


const initialValues = {
  company: "",
  position: "",
  link: "",
  date: "",
  note: "",
};

export default function Form() {
  const [values, setValues] = useState(initialValues);

  return (
        <form>
          <input
            value={values.company}
            onChange={(e) => setCompany(e.target.value)}
            label="Company"
          />
 //...


Enter fullscreen mode Exit fullscreen mode

Step 2: Handle multiple input change

  • The goal here is to handle ALL inputs with a single onChange handler
  • In order to update and keep track of our input fields every time they change, we need to create a handleInputChange function (see below)
  • What's happening here? (quick recap)
    • First, we're using object destructuring to get or extract the name and the value attributes from our inputs (look at the the comments below - they're equivalent)
    • Then, we're updating our values state object with the existing values by using the setValues() function and the spread operator
    • And finally, we're updating the value of the event that was triggered by that onChange with this ES6 syntax: [name]: value
    • This is a very important step! We need to add a name attribute to our inputs and [name]: value here means that we're setting a dynamic name property key (taken from our inputs - e.g. company: e.target.value) which will be equal to the value of our current input state.

Reference: React Docs



 //... 

  const handleInputChange = (e) => {
    //const name = e.target.name 
    //const value = e.target.value 
    const { name, value } = e.target;

    setValues({
      ...values,
      [name]: value,
    });
  };

  return (
        <form>
          <input
            value={values.company}
            onChange={handleInputChange}
            name="company" //IMPORTANT 
            label="Company"
          />
   // ... 


Enter fullscreen mode Exit fullscreen mode

Step 3: Add handleInputChange to input fields

  • Add the handleInputChange function to the onChange prop of every input field
  • Look at the final code; this is a much cleaner and manageable form 👌🏽


import React, { useState } from "react";

const initialValues = {
  company: "",
  position: "",
  link: "",
  date: "",
  note: "",
};

export default function Form() {
  const [values, setValues] = useState(initialValues);

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setValues({
      ...values,
      [name]: value,
    });
  };

  return (
        <form>
          <input
            value={values.company}
            onChange={handleInputChange}
            name="company"
            label="Company"
          />
          <input
            value={values.position}
            onChange={handleInputChange}
            name="position"
            label="Job Title"
          />
           // ... Rest of the input fields
          <button type="submit"> Submit </button>
        </form>
  );
}


Enter fullscreen mode Exit fullscreen mode

I hope it was useful. All comments and feedback are welcome! 🎊

Oldest comments (23)

Collapse
 
yahaya_hk profile image
Yahaya Kehinde

Amazing Deborah ! ☺️☺️

Collapse
 
donchocska profile image
donchocska

Amazing perofrmance. Very thanks!

Collapse
 
jocanola profile image
Jocanola

Really clean.

Collapse
 
majidmo49787329 profile image
Majid Mohamed

Amazing perofrmance. Very thanks!

Collapse
 
omokay profile image
Omoke Chuku

This is beautiful!

Collapse
 
juliojeanfils1 profile image
Julio Jean Fils

Thank you

Collapse
 
abned08 profile image
Aboubakr Ned

Wow, that exactly what I was looking for

Collapse
 
moreyogesh profile image
Yogesh More

The spread operator has not used the in-class component. and this what I am looking for thanks for the exact answer :)

Collapse
 
gsingh profile image
G.Singh

Thank you so much!

Collapse
 
suhrobmuboraksho profile image
Suhrob Muborakshoev

Thanks for the explanation. Kudos