I'm trying to improve the performance of a long list with changeable items using React.memo
, but I'm getting strange behavior.
Steps to reproduce:
1 - Go to the sandbox here
2 - Press add on the first item
3 - Press add on the second item
import React, { useState } from "react";
const App = () => {
const [list, setList] = useState([
{ id: 1, qtd: 0 },
{ id: 2, qtd: 0 },
{ id: 3, qtd: 0 },
{ id: 4, qtd: 0 }
]);
const onAdd = (id, qtd) => {
setList(
list.map((item) => {
if (item.id === id) {
return { ...item, qtd };
} else {
return item;
}
})
);
};
return (
<ul>
{list.map((item) => (
<Item {...item} onChange={onAdd} />
))}
</ul>
);
};
const Item = React.memo(({ id, qtd, onChange }) => {
console.log("Rendering -> " + id);
return (
<li>
<span>{qtd}</span>
<button onClick={() => onChange(id, qtd + 1)}>Add</button>
</li>
);
}, areEqual);
function areEqual(prev, next) {
return prev.qtd === next.qtd;
}
export default App;
Solved it by using the latest state of list
const App = () => {
const [list, setList] = useState([
{ id: 1, qtd: 0 },
{ id: 2, qtd: 0 },
{ id: 3, qtd: 0 },
{ id: 4, qtd: 0 }
]);
const onAdd = (id, qtd) => {
setList((l) =>
l.map((item) => {
if (item.id === id) {
return { ...item, qtd };
} else {
return item;
}
})
);
};
return (
<ul>
{list.map((item) => (
<Item key={item.id} {...item} onChange={onAdd} />
))}
</ul>
);
};
Also added key as stated by Ngọc Hy
https://codesandbox.io/s/flamboyant-grothendieck-z8uxf?file=/src/App.js