首页 / 文章 / React Query 如何将一个 React Native 应用程序的 API 层代码量减少 500 行

React Query 如何将一个 React Native 应用程序的 API 层代码量减少 500 行

一个真实的 React Native 案例研究,展示了如何通过从手动使用 useEffect 进行数据获取转向 React Query,从而消除重复代码,并提升缓存功能与离线处理能力。

1364 词

简介

不久前,一个你可能熟悉的 React Native 项目遇到了一个常见的问题。

几乎所有需要获取远程数据的界面都遵循相同的模式:

  • 在 useEffect 中实现数据获取逻辑
  • 多个独立的加载状态指示器
  • 自定义的错误处理代码块
  • 手动实现的下拉刷新逻辑
  • 人工设计的重试机制
  • 临时的本地缓存解决方案

从功能上来看,这些做法并没有问题。但在数十个界面中保持一致性却成了巨大的维护负担。

切换到 TanStack 的 React Query 后,团队得以剔除大量重复的网络代码,同时获得了更出色的缓存功能、更清晰的加载管理以及更可靠的离线表现。该库内置了查询缓存、自动后台重取功能以及智能网络处理逻辑,大大减少了手动编写状态管理代码的需求。

下文将通过实际 React Native 应用界面中的案例,对比传统手动实现方式与 React Query 版本的区别。

传统 API 管理方式的问题

典型界面的初始化结构大致如下:

const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const [error, setError] = useState(null);

useEffect(() => {
  fetchData();
}, []);
const fetchData = async () => {
  try {
    setLoading(true);
    const response = await api.getPosts();
    setData(response);
  } catch (err) {
    setError(err);
  } finally {
    setLoading(false);
  }
};

这种样板代码在整个应用中反复出现。

每个界面都需要独立管理:

  • 加载状态标志
  • 错误状态标志
  • 重试处理逻辑
  • 下拉刷新逻辑
  • 独立的缓存机制
  • 手动触发重新获取数据
  • 随着应用规模的不断扩大,这种重复的模式越来越难以保持一致性。

    React Query 的出现

    使用 React Query 重写后的同一界面,简化为如下形式:

    const { data, isLoading, error, refetch } = useQuery({
      queryKey: ["posts"],
      queryFn: fetchPosts,
    });
    

    这就是全部的实现代码。

    React Query 会自动处理以下所有功能:

    • 加载状态指示
    • 错误状态处理
    • 去重重复的请求
    • 在后台重新获取数据
    • 缓存管理
    • 重试失败的请求
    • 响应网络重新连接

    这些功能大多开箱即用,还可以通过 staleTime、gcTime、重试配置以及重新获取数据设置等选项进行调优。

    对比一:网络请求

    使用 React Query 之前

    想象有三个独立的屏幕,都需要相同的用户资料数据。

    由于没有共享的缓存层,每个屏幕都会单独发起请求:

    Profile Screen → API Call
    Settings Screen → API Call
    Dashboard Screen → API Call
    

    结果:为相同的数据进行了三次独立的网络调用。

    使用 React Query 之后

    Profile Screen → API Call
    Settings Screen → Cached Data
    Dashboard Screen → Cached Data
    

    这次的结果:仅需要一次网络调用。

    React Query 会将结果存储在查询键下,并将该缓存数据共享给所有请求该数据的组件。之后任何请求相同键的屏幕都能立即获取到缓存值,同时后台的自动刷新功能还能默默保持数据最新。

    实际应用效果

    在用户频繁访问的屏幕上,这会带来以下好处:

    • 发送到 API 的重复请求大幅减少
    • 后端服务器的负载降低
    • 屏幕之间的切换更加流畅

    对比 #2:缓存效率

    可以说,缓存是 React Query 发挥最大价值的地方。

    当相同的查询在其缓存副本失效之前被再次请求时:

    useQuery({
      queryKey: ["products"],
      queryFn: getProducts,
      staleTime: 300000,
    });
    

    界面可以立即显示缓存数据,React Query 可选择在后台静默地刷新它。缓存条目会被保留下来,并最终根据您设定的规则进行垃圾回收。

    实际示例

    以一个电商应用的产品列表页面为例。

    如果没有缓存,打开该页面意味着:

    Open Products
    ↓
    Network Request
    ↓
    Navigate Back
    ↓
    Open Products Again
    ↓
    Network Request
    

    使用 React Query 后,同样的流程变为:

    Open Products
    ↓
    Network Request
    ↓
    Navigate Back
    ↓
    Open Products Again
    ↓
    Instant Cached Data
    

    不同之处在于,使用该应用的用户会明显感受到更流畅的体验。

    对比 #3:加载状态

    在采用 React Query 之前,要跟踪加载状态就需要处理多个布尔值:

    const [loading, setLoading] = useState(false);
    const [refreshing, setRefreshing] = useState(false);
    const [isRetrying, setIsRetrying] = useState(false);
    

    之后,只需一次钩子调用即可获取所需的一切:

    const {
      isLoading,
      isFetching,
      isRefetching,
    } = useQuery(...)
    

    React Query 能区分首次加载与后续的背景请求,这使得相关 UI 逻辑更易于理解。

    实际好处

    应用无需在每次请求时都显示全屏加载器,而是可以区分不同情况:

    • 初始加载:全屏加载器
    • 背景刷新:小型且不显眼的加载指示器
    • 数据已缓存:完全没有可见的干扰

    这样能让使用应用的用户感受到更出色的响应速度。

    对比 #4:离线支持

    团队往往容易低估离线功能的重要性。

    手动处理这种方式通常如下:

    Check Connectivity
    Pause Requests
    Retry Later
    Handle Errors
    Refetch On Reconnect
    

    这意味着需要在整个代码库中分散编写专门的连接逻辑。

    React Query 提供了内置的在线与离线管理功能,同时还具备能响应重新连接事件的重新获取机制。在 React Native 中,你可以结合平台的网络状态监听器使用 onlineManager 来实现这一功能。

    例如:

    onlineManager.setEventListener(...)
    

    React Query 还可以配置为以离线优先的模式运行,从而相应地调整其网络行为。

    实际示例

    以新闻阅读应用为例。

    在一天之内,用户的连接状态可能如下:

    • 早晨:在线
    • 下午:离线
    • 晚上:重新上线

    在这段时间内,之前缓存的文章依然可以正常阅读,而一旦恢复连接,新内容就能自动同步。

    实际应用场景

    1. 新闻类应用

    这样做的好处:

    • 缓存的文章
    • 自动后台刷新
    • 降低整体API流量
    • 离线时仍可继续阅读

    2. 电子商务应用

    其带来的好处:

    • 缓存产品列表
    • 提前预取分类信息
    • 更快地在各板块之间切换
    • 显著提升购物体验的流畅度

    React Query还支持在切换页面之前就预取数据,从而缩短等待时间。

    3. 控制面板应用

    其带来的好处:

    • 能自动刷新的组件
    • 在多个界面之间共享缓存
    • 减少网络通信量
    • 整体状态管理更为简单

    这种模式尤其适合分析控制面板和管理员界面。

    我们实际移除了哪些内容

    迁移完成后:

    已移除

    • 自定义的加载状态处理机制
    • 手动重试代码
    • 重复的API调用
    • 下拉刷新的模板代码
    • 自制的缓存逻辑
    • 手动重新获取数据的管理功能

    已添加

    • React Query库本身
    • 查询键
    • 一个QueryClient实例

    最终效果是:大约500行的API处理代码不再需要。

    何时不需要使用React Query

    在以下情况下,使用React Query可能有些过度:

    • 您的应用仅进行少量API调用
    • 底层数据几乎不会变化
    • 确实不需要缓存功能
    • 离线状态对您的应用而言无关紧要

    不过,对于大多数生产级应用而言,其带来的好处往往很快就能超过最初的学习成本。

    总结

    React Query并不仅仅是另一种获取数据的方式。

    它实际上是一种完整的服务器状态管理解决方案,不仅能减少重复的API代码,还能提升缓存效率、加载表现、网络利用率以及离线使用体验。

    这里最大的收获并非单纯的性能提升,而是复杂度的降低。

    代码更少,错误更少,使用应用的用户体验也更好。

    正是这种综合优势使得进行迁移变得值得。