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

为何该HOC会导致RTK Query陷入无限请求循环?

问题原因

你的withLoading高阶组件在isLoading为true时,会直接渲染Loading...而不渲染被包裹的Nav组件,这会导致Nav被卸载。而Nav内部的useAuthenticateQuery会在组件挂载时自动发起请求,卸载时取消请求。

当服务器宕机请求失败时,RTK Query默认会触发重试机制,进而形成无限循环:

  1. Home中isLoading变为true,HOC渲染Loading,Nav卸载,请求被取消;
  2. RTK Query检测到请求失败(被取消也算失败场景),发起重试,isLoading再次变为true;
  3. 重试请求再次失败,isLoading变为false,HOC渲染Nav,Nav挂载后再次触发useAuthenticateQuery发起请求;
  4. 重复上述流程,陷入无限循环。
解决方案

有两种可行的修复方式,可根据需求选择:

方式一:始终渲染Nav组件,避免卸载

修改Loading.tsx中的高阶组件,确保不管isLoading状态如何,被包裹的组件始终存在(可通过样式叠加Loading层),这样组件不会被卸载,也就不会重复触发请求:

import React, { FC } from "react";

interface props {
  isLoading: boolean;
}

export function withLoading<T extends props = props>(WrappedComponent: FC<T>) {
  const ComponentWithLoading = (props: T) => (
    <div style={{ position: 'relative' }}>
      {/* 叠加Loading层,isLoading时显示 */}
      {props.isLoading && (
        <div style={{ 
          position: 'absolute', 
          top: 0, 
          left: 0, 
          right: 0, 
          bottom: 0, 
          background: 'rgba(255,255,255,0.8)', 
          display: 'flex', 
          alignItems: 'center', 
          justifyContent: 'center' 
        }}>
          Loading...
        </div>
      )}
      {/* 始终渲染原组件 */}
      <WrappedComponent {...props} />
    </div>
  );

  // 添加调试用的组件名称
  ComponentWithLoading.displayName = `WithLoading(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;

  return ComponentWithLoading;
}

方式二:将请求逻辑移到父组件,避免子组件触发请求

把useAuthenticateQuery从Nav移到Home组件,将数据通过props传给Nav,这样Nav只负责展示数据,不会触发请求:

修改Nav.tsx

import { FC } from "react";
import { withLoading } from "../../components/Loading";

// 定义Nav的props类型
interface NavProps {
  userData?: {
    displayName?: string;
    email?: string;
  };
  isLoading: boolean;
}

const Nav: FC<NavProps> = ({ userData }) => {
  return (
    <h1>
      {userData?.displayName} {userData?.email}
    </h1>
  );
}

export default withLoading(Nav);

修改index.tsx

'use client'
import Nav from "./login/Nav";
import { useAuthenticateQuery } from "@/store";

export default function Home() {
  const { data, error, isLoading, refetch } = useAuthenticateQuery();
  
  return (
    <Nav isLoading={isLoading} userData={data?.data} />
  )
}

内容的提问来源于stack exchange,提问作者João Pedro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:45:39