Thank you for all your comments and helpful remarks. following your advices, please find below a code sandbox link
https://codesandbox.io/s/magical-butterfly-uk0fjq?file=/src/item.js
which may help you figure out the issue.
Everything is obvious in the console
, with multiple logs, which, given the current scale of the example, does not pose any performance issue, but which could if there were a long list of items.
So the question is, how to proceed for preventing items which are not deleted from re-rendering, in spite of the fact that the parent (ItemList
) re-renders.
The console
shows the Item
rendering.
As stated previously, I have used a useMemo
+ useCallback
combination, but the result proved to be unstable.
Hope this example will help and be more explicit.
EDIT
regarding the console
log
, strangely, the sandbox example logs 2 times App
, 2 times ItemList
and 12 times Item
, whereas on the computer it logs only 1-1-6 times
So, if you want to minimize the re-renders of the items, you need to make sure of a few things
You can use React.memo
on the component you want, which will prevent re-renders when the props/state do not change.
so, use
export default React.memo(Item);
instead of
export default Item;
When you render the Item
component you pass deleteItem
as a prop with a value that is received from the App
component. However, this function is not a stable (it is redefined each time the App component renders. And since the App
holds the items
state, it will rerender after each deletion. This will trigger a new deleteItem
to be defined, and that will cause the Item
to re-render.
To make this stable, you need two things.
React.useCallback
which re-uses the same function when its dependencies remain the same.function
form of the setItems
so, instead of
const deleteItem = (newItem) => {
const newItemList = items.filter(
(item) => item.reference !== newItem.reference
);
setItems(newItemList);
};
use
const deleteItem = React.useCallback((itemToDelete) => {
setItems((currentItems) =>
currentItems.filter((item) => item.reference !== itemToDelete.reference)
);
}, []);
You also have an issue in your code, where you .map
the data but then before returning each Item
you push it in an array and return that instead. Just return the <Item ..>
So instead of
{props.data.map((item, index) => {
const newList = [];
newList.push(
<Item
deleteItem={props.deleteItem}
key={item.reference}
item={item}
></Item>
);
return newList;
})}
do
{props.data.map((item, index) => {
return (
<Item
deleteItem={props.deleteItem}
key={item.reference}
item={item}
></Item>
);
})}
Updated codesandbox with all changes: https://codesandbox.io/s/twilight-water-9iyobx