Skip to content

useSWR 和 axios 的封装 #76

@inkjuncom

Description

@inkjuncom

普通的 axios 封装

import axios from "axios";
import type {
  AxiosInstance,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";

const apiClient: AxiosInstance = axios.create({
  baseURL: "/api",
  timeout: 10000,
  headers: {
    "Content-Type": "application/json",
  },
});

apiClient.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

apiClient.interceptors.response.use(
  (response: AxiosResponse) => {
    return response;
  },
  (error) => {
    return Promise.reject(error);
  }
);

export default apiClient;

引入类型

// 引入 SWR 核心库及相关类型
import useSWR, { type SWRConfiguration, type SWRResponse } from "swr";
// 引入提前封装好的 axios 实例(包含基础配置、拦截器等)
import apiClient from "./axios";

// 定义后端接口返回的通用数据结构
export interface ApiResponse<T = any> {
  code: number; // 状态码(如 0 成功、1 错误)
  msg: string;  // 提示信息(如 "请求成功"、"参数错误")
  data: T;      // 实际返回的业务数据,用泛型 T 适配不同数据类型
}

// 定义请求配置的接口,描述发起请求需要的核心参数
export interface RequestConfig {
  url: string;
  method?: "get" | "post" | "put" | "delete" | "patch";
  data?: Record<string, any> | FormData;
  params?: Record<string, any>;
  headers?: Record<string, string | number | boolean>;
}

封装核心 fetcher 函数(请求执行层)

fetcher 是 SWR 要求的 "数据获取函数",SWR 会把 key 传给这个函数,由它来实际发起请求并返回数据。这里封装的 fetcher 实现了对 axios 请求的统一封装。

export const fetcher = async <T>(config: RequestConfig): Promise<T> => {
  try {
    const response = await apiClient.request<T>({
      url: config.url,
      method: config.method,
      data: config.data,
      params: config.params,
      headers: config.headers,
    });
    return response.data;
  } catch (error) {
    throw error;
  }
};

封装 useRequest

export const useRequest = <T>(
  key: string | null | RequestConfig,
  config?: SWRConfiguration
): SWRResponse<T, Error> => {
  // 如果 key 为 null 或 undefined,不发起请求
  if (!key) {
    return useSWR<T, Error>(null, config);
  }

  // 处理 key 为字符串的情况,转换为 RequestConfig
  const requestKey =
    typeof key === "string" ? { url: key, method: "get" as const } : key;

  return useSWR<T, Error>(requestKey, fetcher, config);
};

// GET 请求钩子
export const useGet = <T>(
  url: string | null,
  params?: Record<string, any>,
  config?: SWRConfiguration
): SWRResponse<T, Error> => {
  const requestKey = url ? { url, method: "get" as const, params } : null;
  return useRequest<T>(requestKey, config);
};

// 支持 Suspense 的通用请求钩子
export const useRequestSuspense = <T>(
  key: string | null | RequestConfig,
  config?: Omit<SWRConfiguration, "suspense">
): SWRResponse<T, Error> => {
  return useRequest<T>(key, { ...config, suspense: true });
};

// 支持 Suspense 的 GET 请求钩子
export const useGetSuspense = <T>(
  url: string | null,
  params?: Record<string, any>,
  config?: Omit<SWRConfiguration, "suspense">
): SWRResponse<T, Error> => {
  const requestKey = url ? { url, method: "get" as const, params } : null;
  return useRequestSuspense<T>(requestKey, config);
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions