【问题标题】:Change in state not reflecting in function in Next.Js状态变化未反映在 Next.Js 中的功能中
【发布时间】:2021-09-18 02:13:13
【问题描述】:

我有一个功能组件,它呈现出一系列产品。我从它的道具中获取产品数组,并使用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 的情况下定义普通的旧箭头函数。
  • @David784 非常感谢!这似乎解决了这个问题!我确实尝试在没有useCallback 的情况下单独使用handleFiltering 函数,但这并没有解决问题。没有记住所有内容似乎已经解决了这个问题。

标签: javascript reactjs react-hooks next.js use-state


【解决方案1】:

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

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

真正重要的部分是,过度使用记忆化意味着这些函数引用了handleFiltering 的旧副本,它存在于originalItems 仍然是一个空数组的范围/上下文中。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    • 2023-02-13
    • 1970-01-01
    相关资源
    最近更新 更多