[英]How to call react hook inside of a react useCallback
我有一个 next.js 反应应用程序。
我的应用程序中有一部分称为“横幅”,我正在使用上下文 API 构建“商店”。但是,当我在页面中调用“useFetchBanners”function 时,出现以下错误。 这个function用来设置页面的初始state。
- 无法在回调内调用 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.