繁体   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