You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:45:33