How to DRY inputs with React hooks

by||1 min read

Let's assume we have a customer form where we need to gather information about the customers first name, last name and the email address. All three are simple text inputs. But, in plain ReactJS code we would repeat code over and over again:

import React, {useState} from 'react';

const CustomerForm = () => {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [emailAddress, setEmailAddress = useState('');

  return (
    <form>
      <input name="first-name" type="text" onChange={event => setFirstName(event.target.value)}/>
      <input name="last-name" type="text" onChange={event => setLastName(event.target.value)}/>
      <input name="email-address" type="text" onChange={event => setEmailAddress(event.target.value)}/>
    </form>
  );
}

The logic behind each input element is the same, it takes the on change event, extracts the value and sets the value in our local state.

Using Hooks to remove repetitive code

We can now "extract" the common code of setting the value and the input tag to a custom React hook. The hook will take care of the state, render the HTML tag and update the value for us:

import React, {useState} from 'react';

function useInput(properties = {}) {
  const [value, setValue] = useState('');
  const input = <input
    value={value}
    onChange={event => setValue(event.target.value)}
    {...properties} />

  return [value, input];
}


If you are familiar with the concept of hooks in React, you will feel at home with this code. We construct an input element, bind the local state and the update function to it and return a pair of value and element as our hook result. Finally we can refactor our form as follows:

const CustomerForm = () => {
  const [firstName, firstNameInput] = useInput({name: "first-name", type: "text"});
  const [lastName, lastNameInput] = useInput({name: "last-name", type: "text"});
  const [emailAddress, emailAddressInput] = useInput({name: "first-name", type: "text"});

  return (
    <form>
      {firstNameInput}
      {lastNameInput}
      {emailAddressInput}
    </form>
  );
}

We got rid of the repetitive code and can still access firstName, lastName and emailAddress, which are updated on each change for us.

Thank you for reading this far! Let’s connect. You can @ me on Twitter (@debilofant) with comments, or feel free to follow. Please like/share this article so that it reaches others as well.

© Copyright 2022 - Ersocon - All rights reservedVer. 2.3.5.2