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

TypeScript/React中Axios调用报错:'() => AxiosCacheInstance'无get属性

React+TypeScript Axios客户端重构报错解决及代码优化

一、核心报错原因及解决

你遇到的Property 'get' does not exist on type '() => AxiosCacheInstance'错误,本质是两点问题:

  1. 重构后的apiClient是一个函数,不是直接返回的Axios实例,你直接调用apiClient.get相当于在函数上调用实例方法,自然报错。
  2. 函数里用了useNavigate这个React Hook,它只能在React组件/自定义Hook的顶层调用,不能直接在类组件(AuthService是类)里执行apiClient()获取实例,会违反Hook规则。

下面给两种可行的解决思路:

方案1:改成自定义Hook,适配React组件调用

修改api-client.ts为自定义Hook

// api-client.ts
import axios from 'axios'
import { setupCache } from 'axios-cache-interceptor';
import { useNavigate } from "react-router-dom";
import { useMemo } from 'react';

// 自定义Hook必须以use开头
export function useApiClient() {
  const navigate = useNavigate();

  // 用useMemo缓存实例,避免每次调用Hook都创建新实例
  const apiInstance = useMemo(() => {
    const axiosInstance = axios.create({
      withCredentials: true,
      baseURL: "https://localhost:44372/api/v1/",
      headers: {
        "Content-type": "application/json"
      },
      timeout: 60 * 1000 // 1分钟超时
    });

    axiosInstance.interceptors.response.use(
      (response) => response,
      (error) => {
        // 先判断error.response是否存在,避免网络错误/超时导致的报错
        if (error.response) {
          switch (error.response.status) {
            case 401:
              // 处理未授权逻辑,比如跳登录页
              break;
            case 403:
              navigate("/status/403"); // 建议改成403专属页面,而非404
              break;
            case 500:
              // 处理服务器内部错误,比如提示用户
              break;
          }
        }
        return Promise.reject(error);
      }
    );

    return setupCache(axiosInstance);
  }, [navigate]);

  return apiInstance;
}

修改AuthService为Hook风格

// auth-service.ts
import { useApiClient } from "./api-client";

export function useAuthService() {
  const apiClient = useApiClient();

  return {
    getLoggedInUser: () => apiClient.get(`/Authorization/GetLoggedInUser`),
    getLoggedInUserRoles: () => apiClient.get(`/Authorization/GetSecurityAttributesAsync`),
    testAuthorized: () => apiClient.get('/Authorization/TestAuthorized'),
    testUnauthorized: () => apiClient.get('/Authorization/TestUnauthorized')
  };
}

在React组件中使用

// 示例组件
import { useAuthService } from './auth-service';

function UserProfile() {
  const authService = useAuthService();

  const fetchUserInfo = async () => {
    try {
      const res = await authService.getLoggedInUser();
      // 处理返回数据
    } catch (err) {
      // 处理请求错误
    }
  };

  return <button onClick={fetchUserInfo}>获取用户信息</button>;
}

方案2:不使用Hook,用全局history对象跳转

如果不想改动现有的AuthService类结构,可以用history包创建全局路由对象,替代useNavigate:

创建全局history.ts

// history.ts
import { createBrowserHistory } from 'history';

export const history = createBrowserHistory();

修改api-client.ts

// api-client.ts
import axios from 'axios'
import { setupCache } from 'axios-cache-interceptor';
import { history } from './history';

const axiosInstance = axios.create({
  withCredentials: true,
  baseURL: "https://localhost:44372/api/v1/",
  headers: {
    "Content-type": "application/json"
  },
  timeout: 60 * 1000
});

axiosInstance.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 处理未授权逻辑
          break;
        case 403:
          history.push("/status/403");
          break;
        case 500:
          // 处理服务器错误
          break;
      }
    }
    return Promise.reject(error);
  }
);

export const apiClient = setupCache(axiosInstance);
export { CanceledError } from 'axios';

修改Router配置

// App.tsx
import { Router } from 'react-router-dom';
import { history } from './history';
// 导入你的路由组件
import { RoutesConfig } from './routes';

function App() {
  return (
    <Router history={history}>
      <RoutesConfig />
    </Router>
  );
}

这样你的原AuthService类就可以正常使用,不用做任何修改。

二、其他代码问题提示

  1. 原api-client-old.ts的致命错误:在模块顶层直接调用useNavigate(),这违反了React Hook规则,Hook只能在组件或自定义Hook的顶层调用,运行时必然报错,只是你之前可能没触发到这部分逻辑。
  2. 错误处理的漏洞:没有判断error.response是否存在,当请求超时、断网时,error.response是undefined,此时访问error.response.status会直接崩溃,必须先加判断。
  3. 403跳转逻辑不合理:403是权限不足,跳转到404页面会误导用户,建议改成403专属提示页或登录页。
  4. 实例重复创建问题:如果用方案1的自定义Hook,一定要用useMemo缓存Axios实例,否则每次组件渲染都会创建新实例和拦截器,造成性能浪费。

内容的提问来源于stack exchange,提问作者Chris Fink

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:35:08