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

React中如何仅在Token存在时调用useQuery?解决无限重渲染问题

解决React "Too many re-renders" 无限重渲染问题

问题原因

你遇到的无限重渲染,核心问题出在组件渲染的顶层直接调用了setState:

  • 组件每次渲染时,都会执行localStorage.getItem("Token")的判断逻辑,只要Token存在,就调用setIsEnabledApi(true)
  • 调用setState会强制组件重新渲染,重新渲染时又会再次执行这段判断逻辑,再次触发setState,形成无限循环

解决方案

1. 用useEffect包裹Token判断逻辑

把Token的判断和状态更新放到useEffect里,只在组件挂载或Token变化时执行,避免每次渲染都触发状态更新:

// header.jsx
import { useState, useEffect } from 'react';

const Header = () => {
  const [isUserExists, setIsUserExists] = useState();
  const [userName, setUserName] = useState("");
  const [isEnabledApi, setIsEnabledApi] = useState(false);
  const token = localStorage.getItem("Token");

  // 仅在Token变化时更新接口启用状态
  useEffect(() => {
    if (token) {
      console.log('token exists')
      setIsEnabledApi(true);
    } else {
      console.log('no token')
      setIsEnabledApi(false);
    }
  }, [token]); // 依赖token,只有token变化时才重新执行

2. 优化useQuery的自定义hook实现

你的apiAuth函数本质是封装useQuery,但当前写法不符合React自定义hook规范(自定义hook必须以use开头),且无需把setState函数传入hook,建议重构为标准自定义hook:

// apiAuth.js
import { useQuery } from '@tanstack/react-query';

// 重命名为useApiAuth,符合自定义hook命名规范
export const useApiAuth = (isEnabled) => {
  return useQuery({
    queryKey: ['isUserExist'],
    queryFn: () => {
      console.log('calling query function')
      return IsLoggedIn(); // axios.get("/Auth");
    },
    enabled: isEnabled,
  });
};

3. 在组件中处理接口结果

在Header组件中使用重构后的hook,通过监听接口结果的状态来更新本地状态:

// header.jsx 继续补充
import { useApiAuth } from './apiAuth';

// ... 前面的状态定义和useEffect代码 ...

// 使用自定义hook调用接口
const { data: loginInfo, isSuccess, isError } = useApiAuth(isEnabledApi);

// 根据接口结果更新本地状态
useEffect(() => {
  if (isSuccess && loginInfo) {
    setIsUserExists(true);
    setUserName(loginInfo.data.userName);
    setIsEnabledApi(false); // 验证完成后禁用接口,避免重复调用
  }
  if (isError) {
    setIsUserExists(false);
    setIsEnabledApi(false);
  }
}, [isSuccess, isError, loginInfo]);

return(
  <>
    {isUserExists ? <UserButton /> : <LoginButton />}
  </>
)
};

额外优化建议

  • React Query默认会缓存查询结果,只要queryKey不变,不会重复调用接口,因此可以去掉setIsEnabledApi(false)的逻辑,让React Query自动处理缓存
  • 初始化isUserExists时可以设为null,用来区分“未验证”和“验证失败”状态,避免初始渲染时直接显示登录按钮

内容的提问来源于stack exchange,提问作者Liam neesan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:52:43