Diego Rios
Diego Rios

Reputation: 505

React updating when array filters but not when an element is added

I'm trying to simulate a table where I am able to add and remove products, however the component only updates when component is removed but not when I add a new row. I'm using useState

This is my array:

const rowss = [
 createData(1, 'Zapatillas', 2, 200),
 createData(2, 'Chompas', 2, 100),
 createData(3, 'Sandalias', 10, 300),
 createData(4, 'Teclados', 1, 10),
 createData(5, 'Mascarillas', 10, 2000),
 createData(6, 'Celulares', 1, 200),
 createData(7, 'Vasos', 20, 1000),
];

The createData function is working fine.

This is my useState

const [rows, setRows] = useState(rowss)

const handleDelete = (e, id) => {
  let arr = rows.filter(obj => obj._id !== id)
  setRows(arr)
}

const handleAddUi = (e) => {
  let obj = createData(rows.length + 1, "test", "a", "b")
  let arr = rows
  arr.push(obj)
  setRows(arr)
}

And this is how it's shown:

{rows.map((row) => (
                                <TableRow key={row._id}>
                                    <TableCell component="th" scope="row">
                                        {row.product}
                                    </TableCell>
                                    <TableCell align="center">{row.tr}</TableCell>
                                    <TableCell align="center">{row.mp}</TableCell>
                                    <TableCell align="center">
                                        {
                                            !editActions[row._id] ?
                                                <Fragment>
                                                    <CheckIcon className={classes.products__actionButtonsIcons} />
                                                    <CloseIcon className={classes.products__actionButtonsIcons} onClick={(e) => handleEdit(e, row._id)} />
                                                </Fragment>
                                                :
                                                <CreateIcon className={classes.products__actionButtonsIcons} onClick={(e) => handleEdit(e, row._id)} />

                                        }
                                    </TableCell>
                                    <TableCell className={classes.products__actionButtonsIcons} align="center" onClick={(e) => handleDelete(e, row._id)}><DeleteIcon /></TableCell>
                                </TableRow>
                            ))}

Only when I delete an item the one that I added appears, otherwise it doesn't show.

Upvotes: 1

Views: 415

Answers (3)

classydraught
classydraught

Reputation: 412

Also, make sure you avoid mutation while deleting. You can simply use the splice operator instead of doing filtering and setting the array.

Just use return [...array.splice(i,1)];

//i is going to be the index.

Upvotes: 1

Drew Reese
Drew Reese

Reputation: 202836

The following is a state mutation. Pushing an element into the existing state array object and setting it back in state doesn't allow react to diff correctly and re-render.

let arr = rows
arr.push(obj)
setRows(arr)

Solution is to use a functional state update and shallowly copy previous state into a new array and append the new element.

const handleAddUi = (e) => {
  let obj = createData(rows.length + 1, "test", "a", "b");
  setRows(rows => [...rows, obj]);
}

Upvotes: 2

CertainPerformance
CertainPerformance

Reputation: 370789

In React, you should update state by passing a new reference into the state setter. With

let arr = rows
arr.push(obj)

you're setting the state to the same array that's currently in state, and mutating it.

Always avoid mutation with React state. Create a new array and put it into state instead:

setRows([...rows, obj]);

Upvotes: 2

Related Questions