在 Expo 开发中,引入 TanStack Query (React Query) 是移动端开发的强烈推荐方案。
它不仅仅是一个请求库,而是一套完整的异步状态管理方案,专门解决了 React Native 中最棘手的网络与缓存问题。
1. 为什么它是必选项?
在移动端场景下,TanStack Query 解决了传统 useEffect + useState 难以处理的四大痛点:
- 智能缓存与离线支持:在网络不稳定或离线时展示缓存数据,避免白屏;网络恢复后自动在后台静默更新。
- 应用激活自动刷新 (Focus Refetch) :当用户从后台(如回复微信后)切回 App 时,自动检测并刷新过期数据,确保用户看到的信息永远是最新的。
- 状态管理自动化 :彻底告别手写
isLoading、isError、data等繁琐的样板代码。 - 列表交互集成 :内置了对 下拉刷新 、无限滚动 (Infinite Scroll) 的完美支持,与
FlatList配合天衣无缝。
2. 推荐的技术栈架构
在 React Native 应用中,我们推荐以下的"黄金三角"组合:
- 状态管理 (Server State) :TanStack Query (负责请求去重、缓存、过期策略)
- 网络请求 (Fetcher) :Axios 或 Fetch (负责发送 HTTP 请求)
- 安全存储 (Auth) :Expo Secure Store (负责存储 Token)
3. 生产环境集成指南 (关键)
在 React Native 中使用 TanStack Query,必须手动配置 App 状态监听 和 网络状态监听,否则"切后台自动刷新"等核心功能在真机上将失效。
第一步:安装依赖
Bash
# 核心库
npm install @tanstack/react-query
# 用于监听网络状态(必须)
npx expo install @react-native-community/netinfo
第二步:配置全局 Provider (app/_layout.tsx)
这是最关键的一步。我们需要告诉 TanStack Query 何时 App 处于"前台",以及何时"联网"。
TypeScript
import { useEffect } from 'react';
import { AppStateStatus, Platform } from 'react-native';
import { Slot } from 'expo-router';
import {
QueryClient,
QueryClientProvider,
focusManager,
onlineManager
} from '@tanstack/react-query';
import NetInfo from '@react-native-community/netinfo';
import { useAppState } from '@/hooks/useAppState'; // 假设你有一个 AppState Hook,或者直接写在下面
// 1. 配置网络状态监听 (解决断网重连自动刷新)
onlineManager.setEventListener((setOnline) => {
return NetInfo.addEventListener((state) => {
setOnline(!!state.isConnected);
});
});
// 2. 配置 App 焦点监听 (解决切回前台自动刷新)
function onAppStateChange(status: AppStateStatus) {
// Web 端自带监听,RN 端需要手动触发
if (Platform.OS !== 'web') {
focusManager.setFocused(status === 'active');
}
}
// 3. 初始化 QueryClient (配置全局默认策略)
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 2, // 请求失败自动重试 2 次
staleTime: 1000 * 60, // 数据 1 分钟内认为是"新鲜"的,不触发自动请求
gcTime: 1000 * 60 * 5, // 缓存垃圾回收时间 (5分钟)
},
},
});
export default function RootLayout() {
// 监听 App 状态变化
useEffect(() => {
const subscription = AppState.addEventListener('change', onAppStateChange);
return () => subscription.remove();
}, []);
return (
{/* 你的页面入口 */}
);
}
第三步:在页面中使用
配合 RefreshControl 实现下拉刷新变得非常简单:
TypeScript
import { useQuery } from '@tanstack/react-query';
import { View, Text, FlatList, RefreshControl, ActivityIndicator } from 'react-native';
import axios from 'axios';
// 定义请求函数
const fetchTodos = async () => {
const { data } = await axios.get('https://api.example.com/todos');
return data;
};
export default function TodoListScreen() {
const { data, isLoading, isError, refetch } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});
if (isLoading) return ;
if (isError) return 加载失败,请重试;
return (
item.id.toString()}
renderItem={({ item }) => {item.title}}
// 集成下拉刷新,只需一行代码
refreshControl={
}
/>
);
}
4. 总结
引入 TanStack Query 是 Expo 应用迈向高性能 和高可用性的关键一步。
- 对于开发者:它消除了 90% 的冗余代码和手动状态管理。
- 对于用户:它提供了丝滑的"切后台刷新"和"断网重连"体验。