在useEffect中调用React自定义Hook报错的原因及方案咨询
解决React Query自定义Hook在useEffect中调用的Invalid Hook Call错误
报错原因
- 违反了React Hook的核心规则:所有Hook(包括自定义Hook)必须在函数组件的顶层作用域或其他自定义Hook的顶层调用,不能在
useEffect、条件判断、循环等嵌套结构里调用。 - React依赖Hook的调用顺序跟踪状态,在
useEffect里调用Hook会破坏这个顺序,导致React无法正确管理组件状态,因此抛出「Invalid hook call」错误。 - 你的
useGetIdToken是自定义Hook(内部使用了useQuery),不管怎么封装,只要在useEffect里调用它,就会违反规则,必然报错。
可行解决方案:利用React Query的queryKey自动触发请求
React Query本身支持根据依赖项变化自动重新请求,不需要借助useEffect。只需把code加入到useQuery的queryKey中,就能实现「仅当code变化时触发请求」的需求。
修改后的自定义Hook代码
export const useGetIdToken = (code: string | null) => { const logintype = "kakao"; const { isLoading, data, error } = useQuery({ // 将code加入queryKey,code变化时自动触发新请求 queryKey: ["idToken", code], // 只有code存在时才执行请求,避免空code发起无效请求 enabled: !!code, queryFn: async () => { const res = await axiosInstance.get( `/v1/auth/${logintype}/idtoken?code=${code}`, ); return res.data; }, }); return { idToken: data || null, isLoading, error, }; };
组件中使用方式
const KakaoLogin = () => { const [searchParams, setSearchParams] = useSearchParams(); const code = searchParams.get("code"); // 依然在组件顶层调用自定义Hook,符合规则 const { idToken, isLoading, error } = useGetIdToken(code); // 可通过useEffect监听idToken变化做后续处理 useEffect(() => { if (idToken) { console.log("获取到idToken:", idToken); // 这里可执行登录态存储、页面跳转等操作 } }, [idToken]); if (isLoading) return <div>Loading...</div>; if (error) return <div>登录失败,请重试</div>; return <div>登录成功!</div>; };
关键说明
queryKey: ["idToken", code]:当code变化时,queryKey内容改变,React Query会判定为新查询,自动取消旧请求并发起新请求。enabled: !!code:确保仅当code存在时才执行请求,避免code为null时发起无效API调用。- 组件在顶层调用
useGetIdToken,完全符合Hook规则,不会再触发错误。
内容的提问来源于stack exchange,提问作者silverain
相关产品推荐
相关产品推荐

