Expo (React Native) 最佳实践:TanStack Query 深度集成指南

在 Expo 开发中,引入 TanStack Query (React Query) 是移动端开发的强烈推荐方案

它不仅仅是一个请求库,而是一套完整的异步状态管理方案,专门解决了 React Native 中最棘手的网络与缓存问题。

1. 为什么它是必选项?

在移动端场景下,TanStack Query 解决了传统 useEffect + useState 难以处理的四大痛点:

  • 智能缓存与离线支持:在网络不稳定或离线时展示缓存数据,避免白屏;网络恢复后自动在后台静默更新。
  • 应用激活自动刷新 (Focus Refetch) :当用户从后台(如回复微信后)切回 App 时,自动检测并刷新过期数据,确保用户看到的信息永远是最新的。
  • 状态管理自动化 :彻底告别手写 isLoadingisErrordata 等繁琐的样板代码。
  • 列表交互集成 :内置了对 下拉刷新无限滚动 (Infinite Scroll) 的完美支持,与 FlatList 配合天衣无缝。

2. 推荐的技术栈架构

在 React Native 应用中,我们推荐以下的"黄金三角"组合:

  • 状态管理 (Server State)TanStack Query (负责请求去重、缓存、过期策略)
  • 网络请求 (Fetcher)AxiosFetch (负责发送 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% 的冗余代码和手动状态管理。
  • 对于用户:它提供了丝滑的"切后台刷新"和"断网重连"体验。
相关推荐
~无忧花开~2 小时前
Vue二级弹窗关闭错误解决指南
开发语言·前端·javascript·vue.js
软件技术NINI2 小时前
前端面试题:请描述一下你对盒模型的理解
前端
码事漫谈2 小时前
VS Code终端从入门到精通完全指南
前端·后端
wordbaby2 小时前
Expo (React Native) 本地存储全攻略:普通数据与敏感数据该存哪?
前端·react native
zlpzlpzyd3 小时前
vue.js 3中全局组件和局部组件的区别
前端·javascript·vue.js
浩星3 小时前
css实现类似element官网的磨砂屏幕效果
前端·javascript·css
一只小风华~3 小时前
Vue.js 核心知识点全面解析
前端·javascript·vue.js
2022.11.7始学前端3 小时前
n8n第七节 只提醒重要的待办
前端·javascript·ui·n8n
SakuraOnTheWay3 小时前
React Grab实践 | 记一次与Cursor的有趣对话
前端·cursor