Using a Single onChange Handler for Multiple Inputs in React.js

reactjsYou will often run into situations where you will need to create lots of useState hooks for managing input states.

This particularly happens in the cases where you have a lot of inputs or a multi-step form in ReactJS.

It will look something like this.

import React, { useState } from "react";

interface AppProps {}

const App = (props: AppProps): JSX.Element => {
  const [username, setUsername] = useState<string>("");
  const [email, setEmail] = useState<string>("");
  // Imagine 10 more useState handlers here...

  return (
    <form>
      <input
        required
        type="text"
        name="username"
        onChange={(evt: React.ChangeEvent<HTMLInputElement>): void => {
          const {
            target: { value },
          } = evt;

          setUsername(value);
        }}
        value={username}
      />
      <input
        required
        type="email"
        name="email"
        value={email}
        onChange={(evt: React.ChangeEvent<HTMLInputElement>): void => {
          const {
            target: { value },
          } = evt;

          setEmail(value);
        }}
      />

      {/** Add more fields here...  */}
    </form>
  );
};

This is a simple example but shows that one-to-one mapping of inputs and useState handlers can get hard to manage along with adding some repeated code.

One solution to handle this problem is by using a simple Object in javascript.

You can use the name property from the input field names and then create a map of [name][value] in the onChange handler of the <form> element.

import React, { useState } from "react";

interface AppProps {}

const App = (props: AppProps): JSX.Element => {
  const [changes, setChanges] = useState<>({});

  const formOnChange = (e: React.ChangeEvent<HTMLInputEvent>): void => {
    const newChanges = JSON.parse(JSON.stringify(changes));

    const {
      target: { name, value },
    } = e;

    newChanges[name] = value;
  };

  return (
    <form onChange={formOnChange}>
      <input required type="text" name="username" />
      <input required type="email" name="email" />
    </form>
  );
};

As you can see, we have replaced the useState handler in the 2nd example. In this method, we are dynamically setting the key-value props in the changes state object.

On each input event, the onChange event handler in the <form> event will trigger and update the changes object.

One comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: