簡體   English   中英

嘗試使用 useCallback 獲取數據時掛鈎調用無效

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

我正在嘗試在異步函數中調用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 )中設置兩種狀態,但是每當執行此函數時都會出現錯誤:

未捕獲的錯誤:無效的掛鈎調用。 鈎子只能在函數組件的主體內部調用。 這可能是由於以下原因之一而發生的: 1. 你的 React 和渲染器的版本可能不匹配(例如 React DOM) 2. 你可能違反了 Hooks 規則 3. 你可能有多個 React 副本同一個應用

我在這里打破的鈎子規則是什么? 有沒有辦法從函數中設置這些狀態?

PS:我在這里只使用了useCallback鈎子來通過lodash/debounce調用這個函數

編輯:該函數在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]);

您打破的鈎子規則關注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(...

要詳細了解為什么不能這樣做,我強烈推薦這篇博文

編輯:

要使用去抖動的searchParams ,您不需要去抖動執行調用的函數,而是去抖動搜索的值。 (你實際上根本沒有調用 React.useCallback 的 fetchData 函數,只是直接在你的useEffect使用它)

我建議使用這個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