乐趣区

关于前端:reactquery手把手教程④缓存状态与调试工具

缓存状态与调试工具

写在后面

因为国内较少有比拟零碎的 react-query 教程,因而笔者联合官网文档以及官网课程的内容,心愿写一个较为全面的教程。本文将以各种例子作为切入点,尽可能通俗易懂地解说相干知识点。如果有谬误,还请大家在评论区指出,笔者会尽快改过。

目录

  • 入门 react-query 已于 2022-06-04 更新
  • 深刻查询键及查问函数 已于 2022-06-08 更新
  • 并行申请及依赖申请 已于 2022-06-19 更新
  • 查问后果缓存状态与调试工具 已于 2022-06-23 更新

因为缓存状态处于幕后,难以直观地展示相干的变动,因而本章同时也会介绍调试工具的相干应用,来具体地阐明,并且直观地展示相干状态的变动。

缓存状态

react-query 通常在挂载组件时获取数据;在获取数据后,将数据存储到缓存中,并将该数据提供给组件应用。

在 react-query 获取数据的过程中,次要会经验以下三种状态:

  • loading
  • error
  • success

这三种状态 (status) 的流程关系如下:

graph TD
loading --> success
loading --> error

对于有开发教训的同学应该不难理解,申请接口后,要么胜利,要么失败。

下面的三种状态其实也对应 useQuery 钩子中的 isLoadingisSuccessisError 属性。也能够通过 status 属性,获取到loadingsuccesserror

当 react-query 进行后端申请查问时,会有以下三个状态:

  • idle:闲暇,示意以后不须要从后端获取数据
  • fetching: 获取数据,示意以后正在从后端获取数据
  • paused:暂停,示意本来尝试从后端获取数据,然而通常因为未联网的起因导致暂停

fetchStatus将会在 idlefetchingpaused 这三个状态间经验循环:

graph TD
idle --> fetching
fetching --> paused
paused --> fetching
fetching --> idle

📢留神

在 react-query 中 statusloading状态 (或者isLoadingtrue)指的是第一次从后端获取胜利之前的状态,你能够查看这个在线例子来了解这个状态继续的周期:查看在线例子

fetchStatusfetching状态 (或者isFetchingtrue)指的是每次从后端获取数据的加载状态(蕴含第一次获取数据)。

整个生命周期,举个例子:

如果你应用 react-query 从 Github 的接口申请了 react 的 issue 列表,你此次的申请后果将会在 status 中标记为 successerror,或者从 isSuccessisError 中判断申请胜利或者失败。

申请后端数据胜利后,在写入缓存时,此时的缓存状态是 fresh(最新) 状态,然而很快 (默认过期工夫是0ms) 就会变为 stale(老旧) 状态。

如果应用 react 的 issue 列表的每个组件都被卸载后,issue 列表数据的缓存状态将会被标记为 inactive(不沉闷) 状态。此时数据将不会被删除,直到一段时间后(默认为 5 分钟),react-query 将会从缓存中删除该条数据。

在变为 inactive(不沉闷) 状态之前,该条数据将会在 fresh(最新)stale(老旧)之间来回切换,同时接口申请状态也会在 idlefetching之间切换。

👇🏻上面将详细描述该例子过程的细节

应用 DevTools 来察看缓存状态变动

为了更加直观地察看缓存状态的变动,能够应用 DevTools 进行直观地展现。你须要在你的入口文件中,增加上面的代码

import * as React from 'react';
import {StrictMode} from 'react';
import {createRoot} from 'react-dom/client';
import {QueryClient, QueryClientProvider} from 'react-query';
+ import {ReactQueryDevtools} from 'react-query/devtools';

import App from './App';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
const queryClient = new QueryClient();

root.render(
  <StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
+      <ReactQueryDevtools initialIsOpen />
    </QueryClientProvider>
  </StrictMode>
);

下面的示例代码中,咱们引入并设置了 ReactQueryDevtools 组件的 initialIsOpen 属性,因而将会默认关上调试工具

接着咱们开始申请接口,你能够在调试工具中看到以后所有缓存状态的概览,如下图所示:

你也能够关上在线演示察看,在例子中点击【刷新】按钮,来察看缓存状态的变动。

fresh(最新)数据及 stale(老旧) 数据

react-query 是否会触发查问函数,并从后端接口获取数据,与缓存状态是:fresh(最新)状态或 stale(老旧) 状态无关。如果缓存状态是 stale(老旧),示意该查问将会 有资格 从新获取,但如果缓存状态是 fresh(最新) 的,就不会从新获取。

留神📢

如果你想更好地管制接口申请的频率,请务必记住这些内容。

在默认状况下,后端返回的数据其缓存状态将会立刻 ({staleTime: 0}) 从fresh(最新)状态变为 stale(老旧) 状态。

其实这样做不难理解,因为当你申请到数据后,后端的数据有可能就产生了变动,因而当拿到后端返回的数据霎时,缓存状态就是 stale(古老) 的了。

你能够将配置中的 staleTime,设置一个毫秒数的数字,那么缓存将会在staleTime 毫秒后过期 (从fresh(最新) 变为stale(古老))

留神:此时 staleTime 不能为 0,不然没有任何意义。

在上面的例子中,将 staleTime 设置为了 60s,能够在 DevTools 中察看一下缓存状态:

点击查看在线演示

import * as React from 'react';
import {useQuery} from 'react-query';
import './style.css';

export default function App() {const getRepos = (username) =>
    fetch(`https://api.github.com/users/${username}/repos`).then((res) =>
      res.json());

  const reposQuery = useQuery(['repos', 'facebook'],
    () => getRepos('facebook'),
+    {staleTime: 1000 * 60}
  );
  return (
    <div>
      <button
        onClick={() => {reposQuery.refetch();
        }}
      >
        刷新
      </button>
      <p>
        {reposQuery.isLoading && '首次加载中...'}
        {reposQuery.isFetching && '刷新中...'}
      </p>
      <p>{JSON.stringify(reposQuery.data)}</p>
    </div>
  );
}

如果把 staleTime 设置为Infinity,示意以后查问的数据将只会获取一次,且会在整个网页的生命周期内缓存。

当初应该很分明地理解了,缓存状态是如何从 fresh(最新) 变为 stale(老旧) 的过程了。那么是数据一旦变为 stale(老旧) 就会从新获取么?并不是,而是须要满足肯定的触发条件才能够。上面将介绍这些触发条件:

什么时候会触发从新获取数据操作?

在 react-query 中并不是缓存从 fresh(最新) 转换为 stale(老旧) 状态时,就会从新获取。而是依赖于以下五个触发条件从新获取数据数据:

①组件挂载时

当组件首次加载,将会触发数据的获取。如果组件被卸载后再次被加载,此时也会触发数据的从新获取。

②查询键扭转时

在后面章节的示例中也提到过,当查询键扭转时,将会主动触发数据的从新获取。

ps: 如果你的查询键中有对象,也不要放心 react-query 无奈检测进去变动,因为 react-query 会进行深度比对。

③页面从新被聚焦

当用户把浏览器从新聚焦(比方在浏览器中关上了要调试的页面,之后切换到了 vscode 外面编辑代码,编辑实现后须要看下调试的页面成果,又切换到了浏览器),或者切换标签页(比方开了两个浏览器的选项卡,一个是百度,一个是你的页面,从百度的选项卡切换至你的页面)时,react-query 都会主动从新获取数据。

这个触发条件是默认开启的,如果心愿敞开这个触发条件,能够把 refetchOnWindowFocus 选项设置为 false 来禁止。

④网络从新连贯

在以后用户断网从新联网后,react-query 将会从新获取数据。比方你的用户拿着手机在地下通道中,信号中断导致断网,在用户从地下通道进去时,信号连贯上后,又从新联网,此时数据将会从新获取。

这个触发条件同样是默认开启的。如果心愿敞开这个触发条件,能够把 refetchOnReconnect 选项设置为 false 来禁止。

⑤定时刷新

这是一个须要你本人配置的一个触发条件。当你在配置中设置 refetchInterval 为数字 (代表 xxx 毫秒) 时。无论此时数据是 fresh(最新) 还是 stale(老旧) 的缓存状态,react-query 都会在你设置的毫秒工夫距离内从新获取数据

以上五种就是 react-query 内置的从新获取触发条件。

留神❗️❗️❗️❗️📢

除了定时刷新外,其它的触发器,都须要状态是 stale(古老) 才能够触发,你能够在之前的例子中,尝试先失焦页面后,再聚焦(也就是③的触发条件),你会发现当数据在 fresh(最新) 状态时,并没有从新申请数据。

清理缓存

在缓存状态处于 inactive(不沉闷) 状态或者应用这个查问数据的组件卸载时,超过 5 分钟(默认状况下)后,react-query 将会主动革除该缓存。

如果你心愿自定义这个工夫,你能够应用 cacheTime 配置,上面的例子中将 cacheTime 设置为 0,实现的成果是,当查问数据在 inactive 状态时,立刻从缓存中删除。

const userQuery = useQuery(["user", username],
  () =>
    fetch(`https://api.github.com/users/${username}`)
    .then(res => res.json()),
  {cacheTime: 0}
);

当在缓存中删除查问数据后,此时的体现和这个查问数据从未加载过一样,在查问数据从后端返回前,将看到加载状态,获取到数据后,将看到查问数据。

退出移动版