避免重新渲染未更改的项目
Avoiding re-render unchanged items
我正在尝试使用 React.memo
提高包含可更改项目的长列表的性能,但我遇到了奇怪的行为。
重现步骤:
1 - 转到沙盒 here
2 - 在第一项上按添加
3 - 在第二个项目上按添加
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;
使用列表的最新状态解决了
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>
);
};
还添加了 Ngọc Hy 所述的密钥
https://codesandbox.io/s/flamboyant-grothendieck-z8uxf?file=/src/App.js
我修改了你的添加功能。并将 key 属性添加到项目或 li 元素,因为这有助于反应确定 DOM.
中哪个元素已更改
const onAdd = (id, qtd) => {
const oldList = [...list];
oldList.forEach((element) => {
if (element.id === id) {
element.qtd=qtd;
}
});
setList(oldList);
};
<ul>
{list.map((item) => (
<Item key={item.id} {...item} onChange={onAdd} />
))}
</ul>
我正在尝试使用 React.memo
提高包含可更改项目的长列表的性能,但我遇到了奇怪的行为。
重现步骤:
1 - 转到沙盒 here
2 - 在第一项上按添加
3 - 在第二个项目上按添加
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;
使用列表的最新状态解决了
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>
);
};
还添加了 Ngọc Hy 所述的密钥
https://codesandbox.io/s/flamboyant-grothendieck-z8uxf?file=/src/App.js
我修改了你的添加功能。并将 key 属性添加到项目或 li 元素,因为这有助于反应确定 DOM.
中哪个元素已更改const onAdd = (id, qtd) => {
const oldList = [...list];
oldList.forEach((element) => {
if (element.id === id) {
element.qtd=qtd;
}
});
setList(oldList);
};
<ul>
{list.map((item) => (
<Item key={item.id} {...item} onChange={onAdd} />
))}
</ul>