为什么需要在 React/React Native 项目中使用 React-Query

2025-06-04

为什么需要在 React/React Native 项目中使用 React-Query

介绍

您是否遇到过管理服务器状态的问题?或者发现自己编写的代码冗长又滑稽,只是为了从服务器获取数据?如果您有以上任何一种情况,我真心觉得您需要了解一下 react-query。

服务器状态是实际存储在服务器上的状态,然后临时存储在客户端以便快速访问(如用户数据、交易数据)

React 缺乏标准的数据获取范式,这导致了多个状态管理库的诞生。然而,这些库并不完全支持正确处理异步数据(服务器状态)。异步数据通常在组件级别处理,其中通常会跟踪与其相关的每个状态,例如加载、错误、数据、刷新等。随着跟踪的服务器状态数量的增加,管理服务器状态的难度也会增加。

React Query 是一个能够有效管理和跟踪服务器状态的库。在本文中,我将重点介绍如何使用 React-Query,以及为什么应该在你的下一个应用程序中使用它。

React Query 通常被描述为 React 缺少的数据获取库,但从更专业的术语来说,它使得在 React 应用程序中获取、缓存、同步和更新服务器状态变得轻而易举。

先决条件

您需要掌握以下列出的技术的基本知识

  • 反应
  • React hooks(基础)
  • 状态管理库(基础)

为什么要使用 React Query?

在简单的网络请求/调用中,最重要的三个服务器状态是加载、错误和数据服务器状态。使用状态管理库来存储这些状态效率不高,因为整个应用程序不需要知道这些状态,它们只与需要它们的组件相关。

典型的应用程序全局状态如下所示

const globalState = {
    user: {},
    appSettings: {
      appVersion: "",
      theme: "light", // yes I am a thug
    },
    transactions: {
      data: [],
      transactionLoading: true,
            transactionError: null,
    }
  };
Enter fullscreen mode Exit fullscreen mode

在将状态添加到全局状态管理库之前,我会问自己一个问题:“应用是否需要知道这些数据?” 通常情况下,几乎所有服务器状态都无法通过这个测试。我的应用不需要知道事务何时加载或出错,因为这些状态很可能只在一个组件中使用。由于这些服务器状态并非全局需要,因此下一个最佳决策是创建钩子来帮助管理基本的服务器状态。然而,这并不能消除处理多个服务器状态(例如缓存、刷新、重试等)的难度。React Query 提供了一种一致且直接的服务器状态管理方法,因为所有这些都已被抽象到库中。

说话不值一提,让我们行动起来吧!

安装

npm i react-query
# or
yarn add react-query
Enter fullscreen mode Exit fullscreen mode

样本一

// https://codesandbox.io/s/reverent-sunset-rxwgl?file=/src/App.js
import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState({});
  const [error, setError] = useState(null);
  useEffect(() => {
    async function getRepos() {
      try {
        const repoData = await fetch(
          "https://api.github.com/repos/tannerlinsley/react-query"
        ).then((res) => res.json());
        setData(repoData);
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    }
    getRepos();
  }, []);
  if (loading) return "Loading...";

  if (error) return "An error has occurred: " + error.message;
  return (
    <div className="App">
      <h1>Traditional way of handling server State</h1>
      <div>
        <h1>{data.name}</h1>
        <p>{data.description}</p>
        <strong>👀 {data.subscribers_count}</strong>{" "}
        <strong>{data.stargazers_count}</strong>{" "}
        <strong>🍴 {data.forks_count}</strong>
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode
import { QueryClient, QueryClientProvider, useQuery } from 'react-query'

 const queryClient = new QueryClient()

 export default function App() {
   return (
     <QueryClientProvider client={queryClient}>
       <Example />
     </QueryClientProvider>
   )
 }

 function Example() {
   const { isLoading, error, data } = useQuery('repoData', () =>
     fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>
       res.json()
     )
   )

   if (isLoading) return 'Loading...'

   if (error) return 'An error has occurred: ' + error.message

   return (
     <div>
       <h1>{data.name}</h1>
       <p>{data.description}</p>
       <strong>👀 {data.subscribers_count}</strong>{' '}
       <strong>{data.stargazers_count}</strong>{' '}
       <strong>🍴 {data.forks_count}</strong>
     </div>
   )
 }
Enter fullscreen mode Exit fullscreen mode

比较这些函数可以发现 useQuery hook 如何消除设置三种不同的状态、使用 useEffect、捕获错误并最终将加载设置为 false,处理所有这些可能非常麻烦,并且当管理多个状态(如无限列表或分页服务器状态)时,react-query 的精神开始显现,重新获取查询。

样本二

让我们看一下文档中的Rick and Morty示例,因为我认为这是一个更简洁的示例,可以突出显示 react-query 从您的应用程序中删除了多少复杂性。

Examples.js中

// https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/rick-morty?file=/src/Episodes.js:0-903
import React from "react";
import { Typography, Link } from "@material-ui/core";
import { Link as RouterLink } from "react-router-dom";
import { useQuery } from "react-query";
import fetch from "./fetch";

export default function Episodes() {
  const { data, status } = useQuery("episodes", () =>
    fetch("https://rickandmortyapi.com/api/episode")
  );

  if (status === "loading") {
    return <p>Loading...</p>;
  }
  if (status === "error") {
    return <p>Error :(</p>;
  }

  return (
    <div>
      <Typography variant="h2">Episodes</Typography>
      {data.results.map(episode => (
        <article key={episode.id}>
          <Link component={RouterLink} to={`/episodes/${episode.id}`}>
            <Typography variant="h6">
              {episode.episode} - {episode.name} <em>{episode.airDate}</em>
            </Typography>
          </Link>
        </article>
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

获取剧集数据并根据状态有条件地进行渲染(这里不使用加载服务器状态,因为使用加载作为服务器状态存在一些缺陷,您可以在此处查看 Kent Dodds 的文章https://kentcdodds.com/blog/stop-using-isloading-booleans)。

const { data, status } = useQuery("episodes", () =>
    fetch("https://rickandmortyapi.com/api/episode")
);
Enter fullscreen mode Exit fullscreen mode

“episodes” 字符串称为查询键,用于跟踪和管理数据的缓存。查询键对于查询数据应该是唯一的。如果您离开页面然后返回,数据将立即从缓存中获取(请注意,数据在应用程序关闭时不会保留),并在后台重新获取。这是React-query 中的默认设置之一,值得一看,因为对于初学者来说,它可能会让您感到困惑。

本例中的大多数其他数据获取请求都将遵循此流程,我们尝试从服务器获取数据,如果它在缓存中,我们会获取数据,然后它在后台获取数据,如果不在,它会在前台获取数据,所有这些原始的服务器状态处理和它公开的方法使得 react-query 成为用于服务器状态的正确工具。

概括

因此,您需要在 React/React Native 项目中使用 react-query 的原因如下:

  • 您无需编写冗长的代码来帮助管理服务器状态,react-query 直观地帮助您编写更干净、更简短的代码,因为所有这些管理都被抽象到 react-query 中。
  • 该应用程序几乎总是使用最新的服务器状态进行更新。
  • 您不必处理 useEffects。

致谢

React 查询文档
https://kentcdodds.com/blog/stop-using-isloading-booleans
https://kentcdodds.com/blog/application-state-management-with-react#server-cache-vs-ui-state

感谢DominikArafahLulu的审阅。

Pexels 上的 Anni Roenkae 拍摄的照片

文章来源:https://dev.to/benjamindaniel/why-you-need-to-use-react-query-in-your-react-react-native-project-2oog
PREV
参数和参数——您知道它们的区别吗?
NEXT
在全职开发工作的同时维持业余项目的技巧