React defaultValue is causing the filtering function act different than expected

Viewed 31

I have a list of editable inputs, but when I am filtering out one of the items in a useState array, it filters the one clicked on only when I use the value property, which is uneditable, instead of the defaultValue property, which causes the last item of the array to be removed (not the one clicked on).

Is there a way to remove the right while keeping the input editable?

Here is a sample Fiddle: https://jsfiddle.net/MatanCL/25hLyj6a/1

And my code:

function App () {
  let [myAray1, setMyArray1] = React.useState(['cat', 'dog', 'fish']);
  let [myAray2, setMyArray2] = React.useState(['cat', 'dog', 'fish']);
  return (
    <div>

        Working, but input is uneditable:

        {myAray1.map(animal => <div>
            <input value={animal}/>
            <button onClick={() => {
                const me = animal;
                setMyArray1(myAray = myAray1.filter(animal => animal !== me));
            }}>
                remove
            </button>
        </div>)}

        <br/>

        Removes the wrong one:

        {myAray2.map(animal => <div>
            <input defaultValue={animal}/>
            <button onClick={() => {
                const me = animal;
                setMyArray2(myAray2 = myAray2.filter(animal => animal !== me));
            }}>
                remove
            </button>
        </div>)}
    </div>
  )
}

Thank you all!

2 Answers

You should add key to your inputs. Like:

{myAray2.map(animal =>
   <div>
     <input defaultValue={animal} key={animal} />
     ...
   </div>)
}

The reason for doing this is to tell the keys to React explicitly. Furthermore information please read the official document.

The <input> is not editable because setting value property makes it a Controlled Component

You need to add an onChange event to the input to make it editable.

To make sure you're not deleting the wrong element while using filter, make use of the "Key" to filter the correct item.

Removes the wrong one:

       {myAray2.map(animal => <div>
            <input value={animal} key={animal} onChange={handleOnChange}/>
            <button onClick={() => {
                const me = animal;
                setMyArray2(myAray = myAray2.filter(animal => animal !== me));
            }}>
                remove
            </button>
            <div />)}
Related