Next.Js 中的状态变化未反映在功能中

Change in state not reflecting in function in Next.Js

我有一个功能组件可以呈现一系列产品。我从它的道具中获取产品数组并使用 useEffectuseState 挂钩设置它的状态。

我正在尝试通过获取原始数组和 根据某些条件对其进行过滤。

此组件重新呈现几次,因为它的项是从父项中的 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;

(请注意,我省略了一些代码以减少混乱。taggedWithqueryValue 的值已正确更新,但我省略了那段代码)

我怀疑你过度使用 useCallback。在 运行 您的回调非常昂贵的某些有限情况下,制作 memoized callback 可能会有所帮助。但是您必须非常小心,以确保您的依赖项列表是正确的。

在您的实例中,没有理由记忆 handleQueryValueChangehandleTaggedWithChange,这些可能会导致您的问题。它们没有 itemsoriginalItems 作为依赖项,因此它们没有得到更新。

真正重要的部分是过度使用记忆意味着这些函数引用了 handleFiltering 的旧副本,它存在于 scope/context 中,其中 originalItems 仍然是一个空数组.

摆脱所有 useCallback 可能是最好的方法...如果您开始遇到性能问题并且发现记忆有帮助,您可以随时将其添加回 handleFiltering