updating parent state in a table of inputs

https://codepen.io/yohsii/pen/RwLEOZW

import React,{useState} from "react";
import ReactDOM from "react-dom";

const Table = (props) => {

    let [rows, setRows] = useState([{ age: 21, name: 'hi', comment: 'gone' }]);
    const addRow = () => {
        setRows(rows.concat({ age: 0, name: '', comment: '' }));
    }
    const removeRow = (index) => {
        rows.splice(index, 1);
        setRows(rows);
    }

    return (
        
        <div>
            <div><button type="button" onClick={addRow}>add row</button></div>

            {rows.map((x, i) => {
                        return <Row key={i} row={x} onDelete={removeRow} index={i} />;
            })}

        </div>
            
    );

}

const Row = ({row,onDelete,index }) => {

    return (

        <div key={index}>
            <input readOnly="readOnly" placeholder="age" value={row.age} />
            <input readOnly="readOnly" placeholder="name" value={row.name} />
            <input readOnly="readOnly" placeholder="comment" value={row.comment} />
            <button onClick={() => { onDelete(index); }}>delete</button>
        </div>
        
    );

}

ReactDOM.render(
       <Table/>
  ,
  document.getElementById('root')
);

in the removeRow function of the Table component i'm splicing the row array and expecting the Table components render function to display one less row but it doesn't. any ideas as to why?

not sure what else to add really, let me know if you need any more details.

thanks


Solution 1:

splice method changes the contents of an array by removing or replacing existing elements. To rerender your component you need to generate new Array.In order to generate new Array you can use Array-destructring or using slice method, like this:

const removeRow = (index) => {
    rows.splice(index, 1);
    setRows([...rows]);
}

or

 const removeRow = (index) => {
    rows.splice(index, 1);
    setRows(rows.slice());
}

Solution 2:

As Mr Saeed Shamloo said, but I personally always pass a function to setState like this:

const removeRow = (index) => {
    setRows(rows => rows.splice(index, 1));
}