What causes lodash debouncer "TypeError: Expected a function" error?

What causes lodash debouncer "TypeError: Expected a function" error?

我正在尝试在 React 函数组件中使用 lodash 的 debouncer 方法。当我尝试创建 debouncer-wrapped 回调时,我收到

TypeError: Expected a function

在 useCallback 语句处。我已尝试完成三个或四个示例,但其中 none 个可以在我现有的应用程序中使用。我最近的尝试是 here.

  const [userQuery, setUserQuery] = useState("")
  const [deb, setDeb] = useState("");

  const updateQuery = () => {
      setDeb(userQuery)
      };
      
  //const delayedQuery = useCallback(debounce(updateQuery, 500), []);
  //const delayedQuery = useCallback(debounce(updateQuery, 500), [userQuery]);

  const delayedQuery = useCallback(() => debounce(updateQuery, 500), [userQuery]);
  
  const onChange = e => {
     setUserQuery(e.target.value);

  };
  
  useEffect(() => {
     delayedQuery();
  
     // Cancel the debounce on useEffect cleanup.
     return delayedQuery.cancel;
  }, [userQuery, delayedQuery]);

代码在没有 debounce 包装器和 useEffect 中的相关 return 的情况下整体运行(当然没有任何 debouncing)。

评论中显示了其他变体,但都会导致相同的错误。

我对 React 还算满意,所以我对 React 的理解还有很多差距,这可能是问题所在。

编辑 该消息读给我听,好像 debounce 不被识别为函数。我没有收到有关尝试使用 import { debounce } from 'lodash/has';import { debounce } from 'lodash/fp';

导入去抖动的问题的迹象

错误结果:

我假设提到的 TypeError 是在 useEffect 期间抛出的,因为您没有提供任何堆栈跟踪。

编辑 感谢@Ori Drori 的评论和建议: 将 delayedQuery 更改为以下内容:

const delayedQuery = useCallback(debounce(updateQuery, 500), []);

这样,您将拥有去抖动方法的记忆值,无论如何这将是一个回调,具有可用的 cancel 属性.


上一个答案(仅供参考):

那么您可以尝试将 useEffect 更改为以下内容:

useEffect(() => {
  const query = delayedQuery();
  query();
  
  // Cancel the denounce on useEffect cleanup
  return query.cancel;
}, [userQuery, delayedQuery]);

说明

您可以查看不同类型的方法和回调。我从头说起:

  1. useCallback 只接受任何方法,return 是一个新方法,它将简单地调用提供的方法。它将匹配所提供方法的签名。
  2. 反过来,提供的回调是一个简单的箭头函数,return是一个 debounced 方法。
  3. 根据 lodash 文档,debounced 方法可以立即调用,canceled 或 flushed。

这导致我们在您的 useEffect 中出现以下内容:

  • delayedQuery是一个回调。
  • 您调用 delayedQuery(),其中钩子调用箭头函数。
  • 箭头函数调用 debounce 和 return 的值 — 去抖动的 updateQuery!
  • BUT: 此时,您的查询尚未被调用!此外,由于 只有 return 类型的回调 是去抖函数,所以没有 属性 delayedQuery.cancel.
  • 并且因为 delayedQuery.cancel == undefined,你得到了提到的 TypeError

当您调用 delayedQuery() 时,您 return 去抖函数,而不是调用去抖函数的结果。由于 debounce return 是一个带有 cancel 方法的去抖动函数,而 useCallback 接受一个函数,因此定义 delayedQuery 如下:

const delayedQuery = useCallback(debounce(updateQuery, 500), []);

问题是导入了错误的 lodash 函数。具体我原来是导入的:

import { debounce } from 'lodash/fp';

(根据我的部分理解)这是一个更适用于函数式编程技术的包装器。

在这种情况下,我需要导入:

import { debounce } from 'lodash';