DEV Community

loading...

Dynamic form fields using React with hooks

Vimalraj Selvam
Full stack developer and have a history of QA role
・2 min read

I'm trying to create a form where I'm letting user to add as many number of input fields and also giving an ability to remove any particular added input field.

Adding a field works fine, however, the remove always removes the last field, not the one which I wanted to remove.

function App() {
  const [fields, setFields] = useState([{ value: null }]);

  function handleChange(i, event) {
    const values = [...fields];
    values[i].value = event.target.value;
    setFields(values);
  }

  function handleAdd() {
    const values = [...fields];
    values.push({ value: null });
    setFields(values);
  }

  function handleRemove(i) {
    const values = [...fields];
    values.splice(i, 1);
    setFields(values);
  }

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>

      <button type="button" onClick={() => handleAdd()}>
        +
      </button>

      {fields.map((field, idx) => {
        return (
          <div key={`${field}-${idx}`}>
            <input
              type="text"
              placeholder="Enter text"
              onChange={e => handleChange(idx, e)}
            />
            <button type="button" onClick={() => handleRemove(idx)}>
              X
            </button>
          </div>
        );
      })}
    </div>
  );
}

The code sandbox is here: https://codesandbox.io/s/q555kp8jj?fontsize=14

The same thing works with Class component, here is the code sandbox: https://codesandbox.io/s/wznq443xl?fontsize=14

To reproduce the issue, follow these steps:

  • Add some text in the 1st input text field
  • Add a new text field by clicking on + button
  • Click on X button next to the 1st text field

You can see that the above step removes the 2nd field, not the 1st field.

When I inspect, the fields state is properly updating when I click remove button. Kindly help.

Update: The issue has been solved after making the input to controlled component. Thanks to a reddit user to find the issue. Refer more here

Discussion (4)

Collapse
email2vimalraj profile image
Vimalraj Selvam Author

Solved this issue by making the input as controlled component after a reddit user helped.

Refer here.

Collapse
one_punch_007 profile image
one_piece

It's amazing solution, but when using drop-down instead of input, then having issue. If I have two drop-down, on the base of one selection other drop-down appear and I change value. But if I change again the value of first drop-down, the second drop-down value is not reset in UI. I have around 4 type of second field which appear on the base of first drop-down selection.

Collapse
rayremnant profile image
RayRemnant

Thank you for sharing this, I've used your sample to built the same form as a WordPress Gutenberg block.

Really helpful and clear, sending some good vibes.

Collapse
email2vimalraj profile image
Vimalraj Selvam Author

Glad it helped!