-1

In my app, I have a list of <input />'s. The goal is to be able to add and remove inputs from the list. I added a button next to each input to remove that input and one button at the bottom to add a new input at the end of the list.

The problem is that when I press the remove button of an input, the last input is removed, instead of the input next to the button that was clicked. (So in my example, when you remove the input with value "1", the input with value "3" disappears.)

Here is the code for my App component:

function App() {
  const [elements, setElements] = React.useState([
    <Element value="0" />,
    <Element value="1" />,
    <Element value="2" />,
    <Element value="3" />
  ]);

  const add = () => {
    setElements([...elements, <Element value={String(elements.length)} />]);
  };

  const remove = (index) => {
    setElements([...elements.slice(0, index), ...elements.slice(index+1)]);
  };

  return (
    <div>
      {elements.map((element, index) => (
        <div key={index} id={`element-${index}`}>
          {element}
          <button onClick={() => remove(index)}>Remove</button>
        </div>
      ))}
      <button onClick={add}>Add element</button>
    </div>
  );
}

And here is a link to the codepen: https://codepen.io/brm49024/pen/jOPdQJQ

Brammz
  • 369
  • 1
  • 9
  • 26
  • 3
    Add keys to your Elements. For example: , , , . Since they are in array, they need to have keys so reactDOM can distinguish them. And splice is better method instead of 2x slice. – emsiiggy Mar 30 '20 at 22:33
  • https://stackoverflow.com/questions/28329382/understanding-unique-keys-for-array-children-in-react-js/43892905#43892905 – emsiiggy Mar 30 '20 at 23:07

1 Answers1

1

Changing your remove method as below will work:

const remove = (index) => {
    elements.splice(index,1)
    setElements([...elements]);   
};

PS: I think you should build the Element Component inside the render function's map() itself, and only maintain IDs in the state instead of JSX Elements.

Sunny Patel
  • 194
  • 1
  • 10
  • This answer is good instead you should !== instead of != with keys as number and probably use splice instead of filter – AdMer Mar 30 '20 at 22:50
  • I updated my answer as it won't work completely. When you delete an Element say 2, the render() is called again and this time the has index "2" which is already deleted. Hence I used a usual splice to delete 1 element starting at index. :D – Sunny Patel Mar 30 '20 at 22:55
  • 1
    `splice` does not work as it mutates your state directly, so the setter doesn't trigger a re-render – Brammz Mar 30 '20 at 23:55