简体   繁体   English

尝试使用 useCallback 获取数据时挂钩调用无效

[英]Invalid hook call when trying to fetch data using useCallback

I'm trying to call useState inside an async function like:我正在尝试在异步函数中调用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));
      }
    },
    [],
  );

There are two states I am trying to set inside this fetchData function ( setIsLoading and setIds ), but whenever this function is executed am getting the error:我试图在此fetchData函数( setIsLoadingsetIds )中设置两种状态,但是每当执行此函数时都会出现错误:

Uncaught Error: Invalid hook call.未捕获的错误:无效的挂钩调用。 Hooks can only be called inside of the body of a function component.钩子只能在函数组件的主体内部调用。 This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app这可能是由于以下原因之一而发生的: 1. 你的 React 和渲染器的版本可能不匹配(例如 React DOM) 2. 你可能违反了 Hooks 规则 3. 你可能有多个 React 副本同一个应用

What is this Rule of hooks I am breaking here?我在这里打破的钩子规则是什么? Is there any way around to set these states from the function?有没有办法从函数中设置这些状态?

PS: I only used the useCallback hook here for calling this function with lodash/debounce PS:我在这里只使用了useCallback钩子来通过lodash/debounce调用这个函数

Edit: The function is called inside useEffect like:编辑:该函数在useEffect内部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]);

The hook rule you are breaking concerns useCallback because you are returning it as the result of your fetchData;您打破的钩子规则关注useCallback因为您将它作为 fetchData 的结果返回;

useCallback should be called on top level; useCallback应该在顶层调用; not in a callback, like this:不在回调中,像这样:

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));
      }
    },
    [],
  );

The code you wrote is equivalent to你写的代码相当于

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

or even甚至

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

To read more about why you can't do this, I highly recommend this blog post .要详细了解为什么不能这样做,我强烈推荐这篇博文

edit:编辑:

To use the debounced searchParams , you don't need to debounce the function that does the call, but rather debounce the searched value.要使用去抖动的searchParams ,您不需要去抖动执行调用的函数,而是去抖动搜索的值。 (and you don't actually the fetchData function that calls React.useCallback at all, just use it directly in your useEffect ) (你实际上根本没有调用 React.useCallback 的 fetchData 函数,只是直接在你的useEffect使用它)

I recommend using this useDebounce hook to debounce your search query我建议使用这个useDebounce钩子来消除你的搜索查询

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM