Home > Software engineering >  Weird return of data after splice and setstate
Weird return of data after splice and setstate

Time:02-04

Here's simulate in codesandbox

enter image description here

After remove row

enter image description here

Source code

const [gavRows, setGAVRows] = useState([]);

const handleGAVAddRow = async () => {
    try {
        const item = {
            gav_field: '',
            gav_value: ''
        };
        setGAVRows([...gavRows, item]);
    } catch (error) {
        console.log('error', error)
    }
};

const handleGAVRemoveSpecificRow = (idx) => {
    console.log('idx', idx)
    const tempRows = [...gavRows];
    console.log('tempRows', tempRows)
    tempRows.splice(idx, 1);
    setGAVRows(tempRows)
};


const handleGAVChange = async (idx, e) => {
    const { name, value } = e.target;
    var tempRows = [...gavRows];
    tempRows[idx][name] = value;

    setGAVRows(tempRows)
};


<table className="customgav_section">
    <tbody>
        {
            gavRows.map((item, idx) => {
                console.log('map idx', idx, item)
                return (
                    <tr key={idx}>
                        <td>
                            <Input type="text"
                                name="gav_field" id="gav_field"
                                value={gavRows[idx].field}
                                onChange={(e) => handleGAVChange(idx, e)}
                            />
                        </td>
                        <td>
                            <Input type="text"
                                name="gav_value" id="gav_value"
                                value={gavRows[idx].value}
                                onChange={(e) => handleGAVChange(idx, e)}
                            />
                        </td>
                        <td>
                            <Button outline color="danger" onClick={() => handleGAVRemoveSpecificRow(idx)}><FaMinus /></Button>
                        </td>
                    </tr>)
            })
        }
    </tbody>
</table>

CodePudding user response:

Codesandbox

The problem is you put the wrong input value.

Remember the item object you set is:

const item = {
  gav_field: "", //not field
  gav_value: ""  //not value
};

You should modify code from

<td>
   <Input
     type="text"
     name="gav_field"
     id="gav_field"
     value={gavRows[idx].field}
     onChange={(e) => handleGAVChange(idx, e)}
   />
</td>
<td>
   <Input
      type="text"
      name="gav_value"
      id="gav_value"
      value={gavRows[idx].value}
      onChange={(e) => handleGAVChange(idx, e)}
   />
</td>

To:

<td>
   <Input
     type="text"
     name="gav_field"
     id="gav_field"
     value={gavRows[idx].gav_field}
     onChange={(e) => handleGAVChange(idx, e)}
   />
</td>
<td>
   <Input
      type="text"
      name="gav_value"
      id="gav_value"
      value={gavRows[idx].gav_value}
      onChange={(e) => handleGAVChange(idx, e)}
   />
</td>

CodePudding user response:

Your problem is that you are using the index of the array as the key.

Read why that is bad: https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318

A quick hack was assigning a random number as the key of each item in the gavRows and using that as the key of the element. See updated code: https://codesandbox.io/s/charming-bouman-03zn7

Also, the id of an element must be unique in the DOM so i removed those from the input elements.

  •  Tags:  
  • Related