配置: .env
VITE_API_URL=https://ku.qingnian8.com
App.tsx
import "./App.css";
import WzList from "./pages/channl";
function App() {
return (
<>
<WzList></WzList>
</>
);
}
export default App;
src/pages/channl/index.tsx
import React from "react";
import { useEffect } from "react";
import { useWzList } from "../../hooks/useChannl";
// const WzList: React.FC = () => {
// const { wzList, loading } = useWzList(10, "16");
// console.log("获取的数据", wzList);
// if (loading) return <div>Loading...</div>;
// return (
// <div>{JSON.stringify(wzList)}</div>
// // <ul>
// // {wzList.map((item) => (
// // <li key={item?.id}>{item?.name}</li>
// // ))}
// // </ul>
// );
// };
// export default WzList;
const WzList: React.FC = () => {
const { wzList, loading, error, refetch } = useWzList(10, "16");
// 只在数据变化时记录
useEffect(() => {
// if (wzList.length > 0) {
console.log("获取的数据", wzList);
// }
}, [wzList]);
if (loading) return <div>加载中...</div>;
if (error) return <div>错误: {error}</div>;
return (
<div>
<button onClick={refetch}>刷新数据</button>
<div>{JSON.stringify(wzList)}</div>
</div>
);
};
export default WzList;
src/hooks/useChannl.tsx
import { useState, useEffect, useCallback } from "react";
import { getWzList } from "../api/channl";
import type { WzList } from "../types/channl";
// export const useWzList = (num: number, cid: string) => {
// const [wzList, setWzList] = useState<WzList[]>([]);
// const [loading, setLoading] = useState(false);
// // 使用 useCallback 避免重复创建函数
// const fetchWzList = useCallback(async () => {
// setLoading(true);
// try {
// const data = await getWzList(num, cid);
// setWzList(data);
// } catch (err) {
// console.error("获取文章列表错误:", err);
// } finally {
// setLoading(false);
// }
// }, [num, cid]); // 添加依赖项
// useEffect(() => {
// fetchWzList();
// }, []);
// return {
// wzList,
// loading,
// // refetch: fetchWzList,
// };
// };
// 修改后的 useWzList
export const useWzList = (num: number, cid: string) => {
const [wzList, setWzList] = useState<WzList[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null); // 添加错误状态
useEffect(() => {
const fetchData = async () => {
setLoading(true);
setError(null);
try {
const data = await getWzList(num, cid);
setWzList(data);
} catch (err: any) {
setError("加载文章列表失败");
console.error("获取文章列表错误:", err);
} finally {
setLoading(false);
}
};
fetchData();
// 清理函数:组件卸载时取消请求
return () => {};
}, [num, cid]); // 依赖 num 和 cid
// 独立的重取函数(不包含在 useEffect 中)
const refetch = useCallback(async () => {
setLoading(true);
setError(null);
try {
const data = await getWzList(num, cid);
setWzList(data);
} catch (err) {
setError("重新加载失败");
console.error("重新加载错误:", err);
} finally {
setLoading(false);
}
}, [num, cid]);
return {
wzList,
loading,
error,
refetch,
};
};
src/api/channl.ts
import { get, post } from "../utils/request";
import type { WzList } from "../types/channl";
// 获取用户
const getWzList = async (num: number, cid: string): Promise<WzList[]> => {
return get<WzList[]>("/wxList.php", {
params: { num, cid },
});
};
export { getWzList };
src/utils/request.ts
import axios, {
type InternalAxiosRequestConfig,
type AxiosResponse,
AxiosHeaders,
AxiosError,
} from "axios";
// 1. 创建 Axios 实例
const request = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 10000,
headers: { "Content-Type": "application/json" },
});
// 2. 请求拦截器 (统一添加Token)[1](@ref)
request.interceptors.request.use((config: InternalAxiosRequestConfig) => {
// const token = localStorage.getItem("token");
// if (token) {
config.data = JSON.stringify(config.data);
config.headers = AxiosHeaders.from({
"Content-Type": "application/json",
...config.headers,
});
// }
return config;
});
// 3. 错误统一处理器 (核心分离点)
const errorHandler = (error: AxiosError) => {
if (error.response) {
// 服务器响应错误[6,7](@ref)
const status = error.response.status;
const errorMap: Record<number, string> = {
400: "请求参数错误",
401: "未授权,请重新登录",
403: "禁止访问",
404: "资源不存在",
500: "服务器错误",
};
return Promise.reject(errorMap[status] || `服务器错误(${status})`);
} else if (error.request) {
// 请求已发送但无响应[6](@ref)
return Promise.reject("网络连接超时,请检查网络");
}
// 其他错误[6](@ref)
return Promise.reject("请求配置错误");
};
// 4. 封装GET方法
export const get = async <T>(url: string, params?: object): Promise<T> => {
try {
const response: AxiosResponse<T> = await request.get(url, { params });
return response.data;
} catch (error) {
return Promise.reject(errorHandler(error as AxiosError));
}
};
// 5. 封装POST方法
export const post = async <T>(url: string, data?: object): Promise<T> => {
try {
const response: AxiosResponse<T> = await request.post(url, data);
return response.data;
} catch (error) {
return Promise.reject(errorHandler(error as AxiosError));
}
};
src/types.ts
export interface WzList {
code: number;
data: string;
}