我有一个条目列表,我希望始终根据日期对其进行排序。所以我在 useEffect
钩子中加入了一个排序方法,它应该在添加新条目后运行。
useEffect(() => {
setEntries(entries.sort((a, b) => {
if (a.date > b.date) {
return -1;
}
else if (a.date < b.date) {
return -1
}
else {
return 0;
}
}));
}, [entries])
由于 entries
在依赖数组中,useEFfect
应在条目更改(添加条目)后触发。当 useEffect
运行时,setEntries
被调用,因此状态发生了变化,我认为它应该重新渲染。不幸的是,这并没有发生。
这里出了什么问题?
更新列表的代码:
function addEntry(date, description, header, amount) {
if (!date || !description || !header || amount < 0) {
return;
}
setEntries(prev => ([
{id: Date.now(), date: date, description: description, header: header, amount: amount}, ...prev
]))
setDescription('');
setHeader('');
setAmount('');
}
一开始我尝试在此处合并排序功能,但是尽管此功能可以工作,但很奇怪我在更新后无法在同一函数中访问更新的 entries
。
答案 0 :(得分:2)
useEffect 不连续运行 - 它在组件渲染后运行。除了无限循环,首先列表会呈现未排序,然后以排序的顺序再次重新呈现 - 看起来不像你想要的东西?
您可能正在寻找的是 useMemo
<块引用>useMemo 只会在依赖项之一发生变化时重新计算记忆值。这种优化有助于避免每次渲染时进行昂贵的计算。
const sortedEntries = useMemo(() => {
return [...entries].sort((a, b) => {
if (a.date > b.date) {
return -1;
}
else if (a.date < b.date) {
return -1
}
else {
return 0;
}
});
}, [entries])
答案 1 :(得分:0)
你改变你的状态,在这里也使用回调函数:
setEntries((prevEntries) => [...prevEntries].sort(...))
看起来 useEffect 启动了无限循环。您的依赖项是实体,您尝试在内部对其进行修改。最好在负责添加新条目的函数中对实体进行排序
在你的情况下,只需删除 useEffect 并在 addEntry 函数中移动排序逻辑
function addEntry(date, description, header, amount) {
// ...other code
setEntries(prev => ([
{id: Date.now(), date, description, header, amount},
...prev
].sort(...your code...)))
.... other code
}
答案 2 :(得分:0)
所以就像我在评论中强调的那样,您不应该无条件地更新 useEffect
中的状态,其中该状态是一个依赖项。像这样的事情应该可以为您完成工作:
// after state declarations
const sortedEntries = useMemo(() => entries.sort(...), [entries]);
您的处理程序应更新 entries
而不是 sortedEntries
。每当您更新条目时,都会计算一个新的 sortedEntries。由于它是记忆的,当其他一些不相关的状态更新时,它不会重新计算。