Home > Net >  How can I delete an item from list without re-rendering undeleted Items?
How can I delete an item from list without re-rendering undeleted Items?

Time:05-11

I'm having a performance issue in React. I have a list (ItemList), on which I want to delete some of the items (Item).

I'm using a filter methode to do so, setting the newly filtered list in the App parent component.

The items State in App is updated via the setItems function and goes back to ItemList.

EDIT The items state is an Array of Object, like this :

[
 {name: "NAME 1", reference: "REF 1", description: "LOREM IPSUM"},
 {name: "NAME 2", reference: "REF 2", description: "LOREM IPSUM"},
 {name: "NAME 3", reference: "REF 3", description: "LOREM IPSUM"},
]

It works well, the thing is that it re-renders all the ItemList's Items, namely, the ones which were not deleted, which is superfluous.

I also tried a variant wrapping the returned JSX from Item in useMemo, but this time, the deleteItem function works only once, and does not delete the right Item anyway.

here's the code :

App.js

import React, { useState} from "react";
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import ItemList from "./itemList"

function App() {

  const [items, setItems] = useState([])

  const deleteItem = (newItem) => {
    const newItemList = items.filter(item=> item.reference !== newItem.reference)
    setItems(newItemList)
  }

  return (
    <>
    <div className="App">
      <Router>
        <div id="wrapper">
          <Switch>
            <Route path = "/itemList" exact render = {() => 
                <ItemList
                  data={items}
                  deleteItem ={deleteItem }
                ></ItemList>}>
            </Route>
          </Switch>
        </div>
      </Router>
    </div>
    {console.log("App")}
    </>
  );
}

export default App;

itemList.js

import React, { useEffect, useState } from "react";
import Item from "./item";

const ItemList= (props) => {

    const [itemList, setItemList] = useState([])
//useffect to relaunch the list generation if props.data - the item list state in App - changes
    useEffect(() => {
        const newList = []
        props.data.forEach((item, index) => {
            newList.push(
                    <Item
                        deleteItem={props.deleteItem}
                        key={index}
                        item={item}
                    ></Item>
            )
        })
        setItemList(newList)
    }, [props.data])

    return (
        <>
            <div id="itemList">
                {itemList}
            </div>
            {console.log("Item List")}
        </>
    )
};

export default ItemList;

item.js

import React from "react";

const Item = (props) => {

    const handleDeleteItem = (item) => {
        props.deleteItem(item)
    }

    return (
        <>
            {console.log("Item Line")}
            <div className="ItemLine">
                <table>
                    <tbody>
                        <tr>
                            <th>
                                <div onClick={() => props.deleteItem(props.item)}>
                                     {props.item.name} - {props.item.reference} - {props.item.description}
                                </div>
                            </th>
                        </tr>
                    </tbody>
                </table>
            </div>
        </>
    )
}

export default Item;

item.js (Variant with useMemo)

import React, { useMemo } from "react";

const Item = (props) => {

    const handleDeleteItem = (item) => {
        props.deleteItem(item)
    }

    const itemLine = useMemo(() => {
        return (
            <>
            {console.log("Item Line")}
            <div className="ItemLine">
                <table>
                    <tbody>
                        <tr>
                            <th>
                                <div onClick={() => props.deleteItem(props.item)}>
                                     {props.item.name} - {props.item.reference} - {props.item.description}
                                </div>
                            </th>
                        </tr>
                    </tbody>
                </table>
            </div>
            </>
        )
    }, [])

    return (
        <>
            {itemLine()}
        </>
    )
}

export default Item;

CodePudding user response:

when updating the state you need to spread the previous state first before you update it

 const deleteItem = (newItem) => {
const newItemList = items.filter(item=> item.reference !== newItem.reference)
setItems(prev => (...prev, newItemList))

}

CodePudding user response:

when updating the state you need to spread the previous state first before you update it

and depends of your type you must return array or object spreat operator opened previous array or object and then you was add new data setItems(prev => [...prev, newItemList])

  • Related