Next.Js 中的状态变化未反映在功能中
Change in state not reflecting in function in Next.Js
我有一个功能组件可以呈现一系列产品。我从它的道具中获取产品数组并使用 useEffect
和 useState
挂钩设置它的状态。
我正在尝试通过获取原始数组和
根据某些条件对其进行过滤。
此组件重新呈现几次,因为它的项是从父项中的 ajax 调用加载的。这里的问题是,即使 originalItems
的值最终得到更新,这也不会反映何时调用 handleFiltering
方法。在这个方法中,originalItems
的值仍然是一个空数组。
有人可以解释为什么这个变量的状态没有在这个函数中更新吗?有没有办法解决这个问题?提前致谢!
代码如下:
const ProductList = ({ items }) => {
const [taggedWith, setTaggedWith] = useState("");
const [queryValue, setQueryValue] = useState("");
const [originalItems, setOriginalItems] = useState([]);
const [filteredItems, setFilteredItems] = useState([]);
useEffect(() => {
setOriginalItems(items);
setFilteredItems(items);
}, [items]);
const handleQueryValueChange = useCallback(
(value) => {
setQueryValue(value);
handleFiltering(value, taggedWith);
},
[taggedWith, handleFiltering]
);
const handleTaggedWithChange = useCallback(
(value) => {
setTaggedWith(value);
handleFiltering(queryValue, value);
},
[queryValue, handleFiltering]
);
// PROBLEM HERE
const handleFiltering = useCallback(
(filter, tag) => {
// originalItems is still an empty array here. So as a result, the filteredValues
array is always empty.
const filtered = originalItems.filter((item) => {
if ((!filter || item.title.toLowerCase().includes(filter.toLowerCase())) && (!tag ||
item.tags.includes(tag))) return item;
});
setFilteredItems(filtered);
},
[originalItems]
);
return (
<Page >
<Card>
<ResourceList
items={filteredItems}
loading={loading}
/>
</Card>
</Page>
);
};
export default ProductList;
(请注意,我省略了一些代码以减少混乱。taggedWith
和 queryValue
的值已正确更新,但我省略了那段代码)
我怀疑你过度使用 useCallback
。在 运行 您的回调非常昂贵的某些有限情况下,制作 memoized callback 可能会有所帮助。但是您必须非常小心,以确保您的依赖项列表是正确的。
在您的实例中,没有理由记忆 handleQueryValueChange
和 handleTaggedWithChange
,这些可能会导致您的问题。它们没有 items
或 originalItems
作为依赖项,因此它们没有得到更新。
真正重要的部分是过度使用记忆意味着这些函数引用了 handleFiltering
的旧副本,它存在于 scope/context 中,其中 originalItems
仍然是一个空数组.
摆脱所有 useCallback
可能是最好的方法...如果您开始遇到性能问题并且发现记忆有帮助,您可以随时将其添加回 handleFiltering
。
我有一个功能组件可以呈现一系列产品。我从它的道具中获取产品数组并使用 useEffect
和 useState
挂钩设置它的状态。
我正在尝试通过获取原始数组和 根据某些条件对其进行过滤。
此组件重新呈现几次,因为它的项是从父项中的 ajax 调用加载的。这里的问题是,即使 originalItems
的值最终得到更新,这也不会反映何时调用 handleFiltering
方法。在这个方法中,originalItems
的值仍然是一个空数组。
有人可以解释为什么这个变量的状态没有在这个函数中更新吗?有没有办法解决这个问题?提前致谢!
代码如下:
const ProductList = ({ items }) => {
const [taggedWith, setTaggedWith] = useState("");
const [queryValue, setQueryValue] = useState("");
const [originalItems, setOriginalItems] = useState([]);
const [filteredItems, setFilteredItems] = useState([]);
useEffect(() => {
setOriginalItems(items);
setFilteredItems(items);
}, [items]);
const handleQueryValueChange = useCallback(
(value) => {
setQueryValue(value);
handleFiltering(value, taggedWith);
},
[taggedWith, handleFiltering]
);
const handleTaggedWithChange = useCallback(
(value) => {
setTaggedWith(value);
handleFiltering(queryValue, value);
},
[queryValue, handleFiltering]
);
// PROBLEM HERE
const handleFiltering = useCallback(
(filter, tag) => {
// originalItems is still an empty array here. So as a result, the filteredValues
array is always empty.
const filtered = originalItems.filter((item) => {
if ((!filter || item.title.toLowerCase().includes(filter.toLowerCase())) && (!tag ||
item.tags.includes(tag))) return item;
});
setFilteredItems(filtered);
},
[originalItems]
);
return (
<Page >
<Card>
<ResourceList
items={filteredItems}
loading={loading}
/>
</Card>
</Page>
);
};
export default ProductList;
(请注意,我省略了一些代码以减少混乱。taggedWith
和 queryValue
的值已正确更新,但我省略了那段代码)
我怀疑你过度使用 useCallback
。在 运行 您的回调非常昂贵的某些有限情况下,制作 memoized callback 可能会有所帮助。但是您必须非常小心,以确保您的依赖项列表是正确的。
在您的实例中,没有理由记忆 handleQueryValueChange
和 handleTaggedWithChange
,这些可能会导致您的问题。它们没有 items
或 originalItems
作为依赖项,因此它们没有得到更新。
真正重要的部分是过度使用记忆意味着这些函数引用了 handleFiltering
的旧副本,它存在于 scope/context 中,其中 originalItems
仍然是一个空数组.
摆脱所有 useCallback
可能是最好的方法...如果您开始遇到性能问题并且发现记忆有帮助,您可以随时将其添加回 handleFiltering
。