umi数据请求方案:axios、swr、react-query集成
【免费下载链接】umi A framework in react community ✨ 项目地址: https://gitcode.com/GitHub_Trending/um/umi
引言:为什么需要专业的数据请求方案?
在现代前端开发中,数据请求是应用的核心功能之一。传统的fetch API虽然基础,但在复杂业务场景下往往力不从心。umi作为React社区的主流框架,提供了多种数据请求方案的优雅集成方式。本文将深入探讨umi中axios、swr和react-query三大主流方案的集成与实践。
一、umi内置请求方案概览
1.1 内置请求能力
umi内置了基于fetch的请求方案,通过useRequest hook提供基础的数据请求功能:
import { useRequest } from 'umi';
export default function Page() {
const { data, loading, error } = useRequest('/api/userInfo');
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <div>Hello, {data.name}</div>;
}
1.2 配置请求基础配置
在.umirc.ts或config/config.ts中配置全局请求设置:
export default {
request: {
timeout: 10000,
errorConfig: {
errorPage: '/error',
},
requestInterceptors: [
(url: string, options: any) => {
// 添加认证token
const token = localStorage.getItem('token');
if (token) {
options.headers.Authorization = `Bearer ${token}`;
}
return { url, options };
},
],
responseInterceptors: [
(response: Response) => {
// 统一处理响应
return response;
},
],
},
};
二、axios集成方案
2.1 安装与配置
npm install axios
创建自定义请求实例:
// src/utils/request.ts
import axios from 'axios';
const request = axios.create({
baseURL: '/api',
timeout: 10000,
});
// 请求拦截器
request.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 响应拦截器
request.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
export default request;
2.2 在组件中使用
import React, { useState, useEffect } from 'react';
import request from '@/utils/request';
const UserList: React.FC = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchUsers = async () => {
setLoading(true);
try {
const response = await request.get('/users');
setUsers(response.data);
} catch (error) {
console.error('Failed to fetch users:', error);
} finally {
setLoading(false);
}
};
fetchUsers();
}, []);
if (loading) return <div>Loading...</div>;
return (
<div>
<h2>用户列表</h2>
{users.map(user => (
<div key={user.id}>{user.name}</div>
))}
</div>
);
};
三、SWR集成方案
3.1 安装与基础配置
npm install swr
3.2 基础使用示例
import useSWR from 'swr';
const fetcher = (url: string) => fetch(url).then(res => res.json());
const UserProfile: React.FC<{ userId: string }> = ({ userId }) => {
const { data, error, isLoading } = useSWR(
`/api/users/${userId}`,
fetcher,
{
revalidateOnFocus: false,
refreshInterval: 30000,
}
);
if (error) return <div>Failed to load user</div>;
if (isLoading) return <div>Loading...</div>;
return (
<div>
<h1>{data.name}</h1>
<p>{data.email}</p>
</div>
);
};
3.3 高级特性应用
import useSWR, { mutate } from 'swr';
const TodoList: React.FC = () => {
const { data: todos, error, isLoading } = useSWR('/api/todos', fetcher);
const addTodo = async (title: string) => {
const newTodo = { title, completed: false };
// 乐观更新
mutate('/api/todos', [...(todos || []), newTodo], false);
try {
await fetch('/api/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newTodo),
});
// 重新验证数据
mutate('/api/todos');
} catch (error) {
// 回滚 optimistic update
mutate('/api/todos');
}
};
// 渲染逻辑...
};
四、React Query集成方案
4.1 安装与配置
npm install @tanstack/react-query
配置React Query客户端:
// app.ts
import { RuntimeReactQueryType } from 'umi';
export const reactQuery: RuntimeReactQueryType = {
queryClient: {
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
staleTime: 5 * 60 * 1000, // 5分钟
cacheTime: 10 * 60 * 1000, // 10分钟
},
},
},
devtool: {
position: 'bottom-left',
},
};
4.2 基础查询使用
import { useQuery } from 'umi';
const GitHubStats: React.FC = () => {
const { isFetching, data } = useQuery(
['repoData'],
() => fetch('https://api.github.com/repos/umijs/umi').then(res => res.json())
);
return (
<div className="container">
{isFetching && <p>Loading ...</p>}
{data && <p>UmiJS has {data.stargazers_count} stars now!</p>}
</div>
);
};
4.3 变异(Mutation)操作
import { useQuery, useMutation } from 'umi';
const UserManager: React.FC = () => {
const { data: users } = useQuery(['users'], fetchUsers);
const deleteUserMutation = useMutation(
(userId: string) => fetch(`/api/users/${userId}`, { method: 'DELETE' }),
{
onSuccess: () => {
// 使users查询失效,触发重新获取
queryClient.invalidateQueries(['users']);
},
}
);
const handleDelete = (userId: string) => {
deleteUserMutation.mutate(userId);
};
return (
<div>
{users?.map(user => (
<div key={user.id}>
{user.name}
<button onClick={() => handleDelete(user.id)}>
Delete
</button>
</div>
))}
</div>
);
};
五、三种方案对比与选型指南
5.1 功能特性对比表
| 特性 | axios | SWR | React Query |
|---|---|---|---|
| 缓存机制 | 无内置 | 自动缓存 | 高级缓存策略 |
| 数据同步 | 手动 | 自动重验证 | 自动后台更新 |
| 错误处理 | 手动配置 | 内置重试 | 智能重试机制 |
| 开发工具 | 无 | 简单调试 | 强大DevTools |
| 学习曲线 | 简单 | 中等 | 较陡峭 |
| 包大小 | 小 | 中等 | 较大 |
5.2 选型建议
5.3 性能考量因素
- 包大小影响:axios最小,React Query最大
- 内存占用:缓存策略会影响内存使用
- 网络请求优化:SWR和React Query有自动去重机制
- 渲染性能:合理的缓存可以减少不必要的重渲染
六、最佳实践与常见陷阱
6.1 错误处理统一方案
// 创建统一的错误处理hook
const useApi = () => {
const [error, setError] = useState<Error | null>(null);
const handleError = (err: any) => {
const message = err.response?.data?.message || err.message || '请求失败';
setError(new Error(message));
// 可以在这里添加错误上报
};
const clearError = () => setError(null);
return { error, handleError, clearError };
};
6.2 请求取消机制
import { useEffect } from 'react';
import axios from 'axios';
const useCancelableRequest = () => {
useEffect(() => {
const source = axios.CancelToken.source();
const fetchData = async () => {
try {
const response = await axios.get('/api/data', {
cancelToken: source.token
});
// 处理数据
} catch (error) {
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else {
// 处理其他错误
}
}
};
fetchData();
return () => {
source.cancel('Component unmounted');
};
}, []);
};
6.3 性能优化技巧
- 请求去重:使用相同的key避免重复请求
- 数据分区:按业务模块划分查询key
- 预加载策略:在用户可能操作前预加载数据
- 分页优化:使用无限滚动或虚拟列表
七、实战案例:电商平台数据层设计
7.1 项目结构规划
src/
├── api/ # API接口定义
├── hooks/ # 自定义请求hook
├── types/ # TypeScript类型定义
└── utils/ # 工具函数
7.2 领域模型设计
// types/product.ts
export interface Product {
id: string;
name: string;
price: number;
description: string;
category: string;
images: string[];
}
export interface ProductListParams {
page?: number;
limit?: number;
category?: string;
sortBy?: string;
}
7.3 API层抽象
// api/product.ts
import { request } from '@/utils/request';
export const productApi = {
getProducts: (params: ProductListParams) =>
request.get<Product[]>('/products', { params }),
getProduct: (id: string) =>
request.get<Product>(`/products/${id}`),
createProduct: (data: Partial<Product>) =>
request.post<Product>('/products', data),
updateProduct: (id: string, data: Partial<Product>) =>
request.put<Product>(`/products/${id}`, data),
deleteProduct: (id: string) =>
request.delete(`/products/${id}`),
};
7.4 自定义Hook封装
// hooks/useProducts.ts
import { useQuery } from 'umi';
import { productApi } from '@/api/product';
import { Product, ProductListParams } from '@/types/product';
export const useProducts = (params: ProductListParams = {}) => {
return useQuery(
['products', params],
() => productApi.getProducts(params),
{
staleTime: 5 * 60 * 1000,
keepPreviousData: true,
}
);
};
export const useProduct = (id: string) => {
return useQuery(
['product', id],
() => productApi.getProduct(id),
{
enabled: !!id, // 只有id存在时才发起请求
}
);
};
总结
umi框架为React应用提供了灵活多样的数据请求解决方案。选择合适的技术栈需要综合考虑项目需求、团队经验和性能要求:
- 简单场景:优先选择axios,学习成本低且灵活
- 中等复杂度:SWR提供了良好的开箱即用体验
- 企业级应用:React Query的完整功能栈更适合复杂业务
无论选择哪种方案,都要注意错误处理的统一性、性能优化的系统性以及代码的可维护性。良好的数据层设计是前端应用稳定性的基石,也是开发效率的重要保障。
通过本文的详细讲解和实战案例,相信你已经掌握了在umi项目中集成和使用主流数据请求方案的完整知识体系。在实际项目中,根据具体需求选择最适合的方案,并遵循最佳实践,才能构建出高性能、可维护的前端应用。
【免费下载链接】umi A framework in react community ✨ 项目地址: https://gitcode.com/GitHub_Trending/um/umi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



