簡體   English   中英

如何在 react useCallback 中調用 react hook

[英]How to call react hook inside of a react useCallback

我有一個 next.js 反應應用程序。

我的應用程序中有一部分稱為“橫幅”,我正在使用上下文 API 構建“商店”。但是,當我在頁面中調用“useFetchBanners”function 時,出現以下錯誤。 這個function用來設置頁面的初始state。

  1. 無法在回調內調用 React Hook“useFetchBanners”。 React Hooks 必須在 React function 組件或自定義 React Hook function 中調用。[Error/react-hooks/rules-of-hooks]

橫幅商店.tsx

import { createContext, useCallback, useContext, useState } from "react";
import { AppContext } from "src/contexts/app/AppContext";
import { GetBanners, IGetBannersQuery, IGetBannersResponse } from "src/services/BannersService.";

interface IBannerStore {
    isLoading: boolean;
}

const useStore = () => {
    const appContext = useContext(AppContext);
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const [data, setData] = useState<IGetBannersResponse | null>(null);
    const [error, setError] = useState<any>(null);
    const [searchQuery, setSearchQuery] = useState<IGetBannersQuery>({});

    const fetchBanners = async (params: IGetBannersQuery) => {
        const [results, error] = await GetBanners(params, appContext.token);
        if (results.status !== 200 || error) {
            setError(error);
        }
        setData(results.data || null);
    };

    return {
        isLoading,
        setIsLoading,
        data,
        setData,
        searchQuery,
        setSearchQuery,
        fetchBanners: (params: IGetBannersQuery) => fetchBanners(params),
    };
};

const StoreContext = createContext<any>(null);

export const StoreContextProvider = ({ children }: any) => <StoreContext.Provider value={useStore()}>{children}</StoreContext.Provider>;

export const useIsLoading = () => useContext(StoreContext).isLoading;
export const useSetIsLoading = () => useContext(StoreContext).setIsLoading;
export const useData = () => useContext(StoreContext).data;
export const useSetData = () => useContext(StoreContext).setData;
export const useSearchQuery = () => useContext(StoreContext).searchQuery;
export const useSetSearchQuery = () => useContext(StoreContext).setSearchQuery;
export const useFetchBanners = (params: IGetBannersQuery) => useContext(StoreContext).fetchBanners;

我想在頁面加載時調用 function useFetchBanners來設置初始數據。 (考慮到可能存在的現有瀏覽器參數)

橫幅頁面.tsx

...
   const init = useCallback(async () => {
        if (router.isReady === false) {
            return;
        }
        let loadBrowserSearchParams = null;
        if (!_.isEmpty(router.query)) {
            loadBrowserSearchParams = {
               ...
             }
        }

        // error here
        useFetchBanners(loadBrowserSearchParams);

    }, [router]);

    useEffect(() => {
        init();
    }, [init, router]);

...

似乎我無法在 useCallback 中調用我的 useFetchBanners。

我認為您的鈎子已經正確編寫,您只需要以不同的方式使用它。 在您的組件主體中調用它,它會返回一個 function 給您,然后您可以稍后調用該 function。

// bannersPage.tsx
const fetchBanners = useFetchBanners();

const init = useCallback(async () => {
  if (router.isReady === false) {
    return;
  }
  let loadBrowserSearchParams = null;
  if (!_.isEmpty(router.query)) {
    loadBrowserSearchParams = {
       ...
    };
  }

  fetchBanners(loadBrowserSearchParams);
}, [router]);

useEffect(() => {
  init();
}, [init, router]);

PS,如果效果中只需要init function,可以移到效果里面:

const fetchBanners = useFetchBanners();
useEffect(() => {
  if (router.isReady === false) {
    return;
  }
  let loadBrowserSearchParams = null;
  if (!_.isEmpty(router.query)) {
    loadBrowserSearchParams = {
       ...
    };
  }

  fetchBanners(loadBrowserSearchParams);
}, [router]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM