Manage React state for dynamically generated input elements

Manage React state for dynamically generated input elements

ยท

2 min read

While working on a personal project, I stumbled upon a scenario where the number of input elements rendering on the screen was not fixed, it could be just 1 or 100 or anything in between.

How do you manage React state in such a scenario? Let's find out ๐Ÿ‘‰

Input elements are controlled It is always a good practice to control the input element via React state/Hooks. When you have a fixed number of input elements, it is pretty easy to manage the input fields data. See example below:

export default function App() {
  const [firstName, setFirstName] = useState("");
  const [lastName, setLastName] = useState("");

  return (
    <div className="App">
        <input
          value={firstName}
          onChange={e => setFirstName((e.target.value))}
          placeholder="First Name"
        />
        <input
          value={lastName}
          onChange={e => setLastName(e.target.value)}
          placeholder="Last Name"
        />
      </div> 
  );
}

Now imagine a scenario when the number of input field elements are user controlled. As a developer, you don't know ahead of time the number of elements that the user will add in the page. So you need to have a mechanism in place that would take care of that.

Solution

The dynamically generated inputs will need to have either an order or preset identifiers. Anything through which you can find a reference back to your data.

Say you have an object representing a group of users. Now based on the number of users, the page renders the input fields.

How do we design the state object here?

Each user has a unique id and we can use this id as an identifier to store key(id)/value pairs. It would look something like this:

values = {
  1:"lorem",
  2:"ipsum",
  3:"sodem"
}

In the code above, 1, 2, 3 are the unique ids of the users and the value is what we get back from the input field. Let's see it in action:

export default function App() {
  const [inputValues, setInputValues] = useState();
  const handleChange = (userId) => (e) => {
    setInputValues((values) => ({ ...values, [userId]: e.target.value }));
  };

  return (
    <div className="App">
      {users.map((user) => {
        return (
          <input
            key={user.id}
            value={inputValues[user.id]}
            type="text"
            onChange={handleChange(user.id)}
          />
        );
      })}
    </div>
  );
}

Code explanation

Look at the handleChange method. All it does is use the userId as the key and set the value to e.target.value which is what you get from the input field. The unique userid is your reference point for each input field value.

And this is all I have for this article. Hope this proves useful if you stumble upon this issue and trust me you will! ๐Ÿ˜†๐Ÿ˜†๐Ÿ˜†๐Ÿ˜†

My comment section is open to your feedback. If you want to chat over twitter, you can find me here .

Until next time!