react-query手把手教程⑩-isFetching(是否正在获取数据)

425 阅读3分钟

该系列其他文章可以点击查看专栏👉🏻👉🏻react-query手把手教程系列

介绍

在react-query中开发者可以通过访问isLoading状态,为用户展示loading动画。第一次加载数据完成后,react-query将会把数据存在缓存中,多数情况下就不必再次显示loading动画。

但是react-query也会在后台通过策略自动重新获取数据。在某些情况下,用户可能会想知道这些数据是否正在被后台刷新,此时你就需要isFetching属性。在第一次加载及后面刷新的加载过程中,该属性的值为true

实践

isFetching

可以通过在当前数据的旁边添加一个指示器,表示正在获取后端数据。伪代码如下:

import { Spin, Space } from 'antd';

const User = ({userId}) => {
  const userQuery = useQuery(
    ["user", userId],
    (userId) => fetchUser(userId),
  );
  
  // ①
  if (userQuery.isLoading) {
    return <Spin />;
  }


  return (
    <Space>
      <h1>
        <span>{userQuery.data.name}</span>
        {userQuery.isFetching && <Spin />}
      </h1>
      <p>{userQuery.data.email}</p>
    </Space>
  )
}

由于第一次加载数据时,没有任何数据,此时①只展示加载动画。

在②中由于缓存中已经存储了用户数据,只是在后台重新刷新数据时,在用户名的旁边为用户展示正在获取数据的小动画,并不影响之前缓存数据的展示。

useIsFetching

获取全局isFetching数据

上面介绍的仅仅是单个查询中,获取当前请求的isFetching状态,如果需要进行批量查询,那么就需要使用useIsFetching钩子。

如果你需要一个组件来显示,当前全局是否有后台数据正在获取,可以用下面的例子:

import { Spin } from 'antd';

const QueryLoader = () => {
  const isFetching = useIsFetching();

  if (isFetching) {
    return <Spin />
  }
  
  return null;
}

export default QueryLoader

接着需要在根组件中(index.js/index.tsx)添加该指示器:

import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "react-query";
import App from "./App";


const queryClient = new QueryClient();


const rootElement = document.getElementById("root");
const root = ReactDOM.createRoot(rootElement);


root.render(
  <QueryClientProvider client={queryClient}>
    <App />
    <QueryLoader />
  </QueryClientProvider>,
);

此时,一旦全局查询中,有查询被刷新,将会全局展示加载动画指示器,让用户知道数据正在刷新,但是也不影响当前用户的使用。

基于查询过滤器获取isFetching数据

useIsFetching同样支持传入查询过滤器,如果你不清楚查询过滤器,你可以查看这篇文章👉🏻react-query手把手教程⑧-查询过滤器

还是以github为例,如果你需要在详情页,针对其中所有的查询展示是否加载的动画,那么你只需要下面例子中的RepoLoader组件即可。

import { Spin, Space } from 'antd';

const RepoLoader = ({owner, repo}) => {
  const isFetching = useIsFetching(["repo", owner, repo]);

  if (isFetching) {
    return <Spin />
  }
  
  return null;
}


// ①
const repoQuery = useQuery(["repo", owner, repo]);
const issuesQuery = useQuery(["repo", owner, repo, "issues"]);
const pullRequestsQuery = useQuery(["repo", owner, repo, "pulls"]);


// ②
const userQuery = useQuery(["user", username]);
const userReposQuery = useQuery(["user", username, "repos"]);
const issuesQuery = useQuery(["issues", owner, repo]);

在上面的例子中,①里所有的查询,如果有获取数据的场景下,都会展示RepoLoader。但是②中左右的查询,都不会展示。

这样就能让开发者非常方便地为用户展示,当前数据正在后台加载。

阶段性总结

目前该系列加本文已经有十篇,其中需要认真了解的概念其实有以下几点:

  • useQuery常用的属性,比如:isLoadingisFetchingdata
  • 缓存数据的新旧程度标记,比如:过期(stale)等;以及数据在陈旧状态下,什么时机会自动重新获取数据。
  • 当前查询的状态,比如:活跃(active)、不活跃(inactive
  • 当前查询获取数据的状态,比如获取中(fetching)、已暂停(paused)、请求挂起(idle
  • 合理的去设置查询键(queryKey),方便后续查询过滤器的使用
  • 批量对查询进行:获取加载状态useIsFetching、取消请求cancelQueries、刷新请求(queryClient.refetchQueriesqueryClient.invalidateQueries

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情