【问题标题】:Invalid hook call when trying to fetch data using useCallback尝试使用 useCallback 获取数据时挂钩调用无效
【发布时间】:2020-07-11 23:01:20
【问题描述】:

我正在尝试在异步函数中调用 useState,例如:

const [searchParams, setSearchParams] = useState({});

const fetchData = () => useCallback(
    () => {
      if (!isEmpty(searchParams)) {
        setIsLoading(true); // this is a state hook
        fetchData(searchParams)
          .then((ids) => {
            setIds(ids); // Setting the id state here
          }).catch(() => setIsLoading(false));
      }
    },
    [],
  );

我试图在此 fetchData 函数中设置两种状态(setIsLoadingsetIds),但每当执行此函数时都会出现错误:

未捕获的错误:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用。这可能由于以下原因之一而发生: 1. React 和渲染器的版本可能不匹配(例如 React DOM) 2. 你可能违反了 Hooks 规则 3. 你可能在同一个应用中拥有多个 React 副本

我在这里打破的钩子规则是什么? 有没有办法从函数中设置这些状态?

PS:我这里只使用了useCallback钩子来调用这个函数lodash/debounce

编辑:该函数在useEffect 内部调用,如:

const debouncedSearch = debounce(fetchSearchData, 1000); // Is this the right way to use debounce? I think this is created every render.

const handleFilter = (filterParams) => {
    setSearchParams(filterParams);
};

useEffect(() => {
    console.log('effect', searchParams); // {name: 'asd'}
    debouncedSearch(searchParams); // Tried without passing arguments here as it is available in state.
// But new searchParams are not showing in the `fetchData`. so had to pass from here.
}, [searchParams]);

【问题讨论】:

  • 问题在于 useCallback 而不是 useState;因为你在函数内部调用它,这违反了钩子规则
  • 你是如何使用 fetchData 的?
  • @MohamedELAYADI 添加了如何使用函数的示例代码。
  • 你检查我提出的答案了吗?我将尝试对其进行更新以使其与去抖值一起使用

标签: reactjs react-hooks


【解决方案1】:

你打破的钩子规则关注useCallback,因为你将它作为你的 fetchData 的结果返回;

useCallback 应该在顶层调用;不在回调中,像这样:

const fetchData = useCallback(
    () => {
      if (!isEmpty(searchParams)) {
        setIsLoading(true); // this is a state hook
        fetchData(searchParams)
          .then((ids) => {
            setIds(ids); // Setting the id state here
          }).catch(() => setIsLoading(false));
      }
    },
    [],
  );

你写的代码相当于

const fetchData = () => { return React.useCallback(...

甚至

function fetchData() { return React.useCallback(...

要详细了解为什么不能这样做,我强烈推荐blog post

编辑:

要使用去抖动的searchParams,您不需要对执行调用的函数进行去抖动处理,而是对搜索到的值进行去抖动处理。 (而且你实际上根本没有调用 React.useCallback 的 fetchData 函数,直接在你的useEffect 中使用它)

我建议使用此useDebounce hook 去抖动您的搜索查询

const [searchParams, setSearchParams] = React.useState('');
const debouncedSearchParams = useDebounce(searchParams, 300);// let's say you debounce using a delay of 300ms

React.useEffect(() => {
  if (!isEmpty(debouncedSearchQuery)) {
        setIsLoading(true); // this is a state hook
        fetchData(debouncedSearchParams)
          .then((ids) => {
            setIds(ids); // Setting the id state here
          }).catch(() => setIsLoading(false));
      }
}, [debouncedSearchParams]); // only call this effect again if the debounced value changes

【讨论】:

  • 感谢您的回答。它解决了错误。但是debounce 现在不工作了。你能检查我是否使用正确吗?
猜你喜欢
  • 2021-12-07
  • 1970-01-01
  • 2020-08-13
  • 1970-01-01
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
相关资源
最近更新 更多