成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一個數據獲取竟被 React Query 玩出這么多花樣來!

開發 前端
值得注意的是,“緩存 5 秒鐘”并不是說數據獲取后,過 5 秒鐘就刪掉了,而是說查詢緩存在不活躍(inactive)或未使用(unused),5 秒鐘后數據就被垃圾回收器回收了。

本文是 React Query 系列第二篇,上一篇,我們概述了 React Query 是什么[1],以及它的 3 個核心概念,包括:

  1. 查詢(Queries)
  2. 修改(Mutations),和
  3. 作廢緩存(Query Invalidation)

本次,我們將深入第一個核心概念里的內容——useQuery()。

useQuery() 是 React Query 對外提供一個用于封裝獲取數據請求的包裝 React Hook。

import { useQuery } from 'react-query'

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

  if (isLoading) return 'Loading...'
  if (isError) 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>
  )
}

如你所見,useQuery 本身并不提供請求能力,而是依賴 Fetch API 或 axios 三方庫提供請求能力,useQuery() 做的就是提供響應數據存儲和請求狀態包裝。

接下來,我們就細細來看 useQuery() 的使用

useQuery() API

如果你有看到 useQuery() API 的官方定義[2],就會發現內容非常多。

不過,本文我們先只列最常用的一些。包括:

import { useQuery } from 'react-query'

const {
  data,
  error,
  isError,
  isFetching,
  isLoading,
  isRefetching,
  isSuccess,
  refetch,
} = useQuery(queryKey, queryFn?, {
  enabled,
  onError,
  onSuccess,
  refetchOnWindowFocus,
  retry,
  select,
  staleTime,
})

當然,為了使用 useQuery(),我們還要通過 QueryClientProvider 注入 QueryClient 實例。這部分也是樣板代碼:

import { QueryClient, QueryClientProvider, useQuery } from 'react-query'
import axios from 'axios'

const queryClient = new QueryClient()

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

useQuery() 有賴于 queryClient,這一步是必須的。

接下來,我們要舉的案例都基于 <Example> 進行編寫。開始吧!

基本案例

先來看一個最簡單的例子。

function Example() {
  const { isLoading, isError, error, data } = useQuery(
    'http200',
    () => axios.get('https://httpstat.us/200?sleep=3000')
  )

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

  return (
    <div>
      <p>{ JSON.stringify(data.data) }</p>
    </div>
  )
}

查看效果(3秒 Loading,最后展示數據):

圖片圖片

圖片圖片

這是使用 useQuery() 的最小可運行 DEMO 了。

錯誤重試

當然,useQuery() 還能攔截異常,我們將調用 URL 稍稍修改下。

const { isLoading, isError, error, data } = useQuery(
  'http500',
  () => axios.get('https://httpstat.us/500')
)

查看效果:

圖片圖片

你會看到 isLoading 狀態會維持一段時間。這是因為,對于錯誤響應,useQuery() 默認會做重試。

查看控制臺:

圖片圖片

圖片圖片

這里有 4 條一樣的請求。useQuery 自帶錯誤重試(Retries)機制,默認 3 次,加上原本的第 1 條,一共 4 條。

如果 4 次都失敗了,狀態就由 isLoading 變成 isError。

當然,你是可以通過 retry 選項自定義。

useQuery('http200', () => axios.get('https://httpstat.us/500'), { retry: 1 })

再來看看效果:

圖片圖片

重試 1 次失敗后,就直接報錯了。

retry 還支持設置布爾值:true 表示無限重試,false 表示不做任何重試。

緩存數據

另外,在使用 useQuery() 時,我們傳入的第一個參數是 Query Key。Query Key 是 React Query 內部用來緩存獲取數據的唯一標記,默認會緩存 5 分鐘。

那么如何體現呢?我們可以通過 useQuery() 做一次數據獲取。

function Example() {
  const { isLoading, isError, error, data, refetch } = useQuery(
    'http200',
    () => axios.get('https://httpstat.us/200?sleep=2000')
  )

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

  return (
    <div>
      <p>{ JSON.stringify(data.data) }</p>
      <button onClick={refetch}>refetch</button>
    </div>
  )
}

效果:

圖片圖片

會發現,調用 refetch 的過程中,React Query 在控制臺強制發起了一個請求。

不過在這個階段,左側頁面的數據狀態沒有任何變動——這是由于 React Query 在接受值為 'http200' 的 Query Key 時,發現之前已經緩存過,所以就直接返回了緩存數據。

不過,我們也是有辦法監聽后臺發起的這種請求的狀態的,那就是通過 useQuery() 返回的 isFetching 變量。

const { isLoading, isError, error, data, refetch, isFetching } = useQuery('http200', () => axios.get('https://httpstat.us/200?sleep=2000'))

再通過 isFetching 控制按鈕狀態。

<button disabled={isFetching} notallow={refetch}>{ isFetching ? 'isFeching...' : 'refetch' }</button>

查看效果:

圖片圖片

這樣,我們就能監聽后臺默默進行的數據請求了。

當然,數據緩存時間是可以通過 cacheTime 選項自定義的(單位毫秒(ms))。

useQuery('http500', () => axios.get('https://httpstat.us/500'), { cacheTime: 10 * 60 * 1000 })

以上,我們將緩存時間設定成 10 分鐘。

默認后臺數據的請求行為

useQuery() 還有一個默認行為,非常便捷,就是在網頁從后臺重新切入或者重新聚焦時,useQuery() 會自動觸發后臺數據重新獲取。

圖片圖片

這個機制的原理是,React Query 會監聽網頁的 visibilitychange 和 focus 事件,當 document.visibilityState 為 'visible' 或者觸發 focus 事件時,就會重新請求。

當然,這個行為可以通過 refetchOnWindowFocus 選項禁用掉。

useQuery(
  'http200',
  () => axios.get('https://httpstat.us/200'),
  { refetchOnWindowFocus: false }
)

注意,從 v5 版本開始,refetchOnWindowFocus 啟用時(默認),不再監聽 focus 事件[3],避免意外多出來的后臺請求[4]的發出。

過期時間

經過以上的學習,你可能會有疑問——既然 React Query 有默認幫我們緩存數據,為什么在緩存數據有效期范圍內,還會發起新請求呢?

這就牽扯到另外一個概念,叫過期時間(Stale Time)。

useQuery() 默認獲取到的數據,被認為是過期的。雖然重新獲取數據時,會利用緩存數據,但只是用于臨時展示,新請求獲得的數據,會立即替代過期的緩存數據。

當然,這個行為是可以通過 staleTime 選項自定義(默認 staleTime: 0),其類型定義如下:

staleTime: number | Infinity

當為數值時,單位毫秒(ms),表示數據有效/新鮮期。當 staleTime 設置為 Infinity 時,就表示數據永不過期。在緩存有效期范圍內,useQuery() 會始終使用緩存數據,而不發起新的請求。

useQuery(
  'http200', 
  () => axios.get('https://httpstat.us/200'),
  { staleTime: Infinity }
)

這樣做之后,刷新頁面,在獲取到一次數據后,不管你如何重新切入/聚焦頁面,都沒有新的請求發出——這是因為數據在有效期內,另外還有緩存,就直接返回了。

staleTime 與 cacheTime

不過,staleTime 是如何與 cacheTime 配合起作用的呢?

我們再看一個例子:

function Example() {
  const { isLoading, isError, error, data, refetch, isFetching } = useQuery('http200', () => axios.get('https://httpstat.us/200?sleep=2000'), { staleTime: Infinity, cacheTime: 5 * 1000})
  // ...
}

這里我們設置了數據永不過期,但緩存時間只有 5 秒鐘。不過 5 秒鐘過后,你重新切入頁面,發現還是沒有請求。為什么呢?

圖片圖片

這是因為“緩存 5 秒鐘”,并不是說數據獲取后,過 5 秒鐘就刪掉了!“緩存 5 秒鐘”是指當查詢緩存在不活躍或未使用,5 秒鐘后數據就會被垃圾回收器回收。

那么如何確定“useQuery 查詢的緩存是不活躍或未使用”的呢?很簡單的一個場景,就是使用 useQuery('http200') 的這個組件被卸載了。

我們改動下 App 組件。

export default function App() {
  const [display, setDisplay] = useState(true)

  return (
    // Provide the client to your App
    <QueryClientProvider client={queryClient}>
      <>
        <button onClick={() => setDisplay(!display)}>{ display ? 'hide' : 'show' }</button>
        { display && <Example /> }
      </>
    </QueryClientProvider>
  )
}

待 <Example /> 數據渲染完成后。

圖片圖片

我們再將 <Example /> 銷毀,等 5 秒鐘再展示<Example /> ——雖然設置了數據永不過期,但緩存時間只有 5 秒鐘,現在緩存也沒有(被回收了),因此就會發現新請求出來了。

圖片圖片

正是因為 cacheTime 這個名稱會讓人產生歧義,因此從 v5 版本開始,`cacheTime` 選項改名[5]為更符合其含義的 gcTime 了。

總結

本文我們講解了 useQuery() API 的使用。

首先要知道的是,useQuery 本身并不提供請求能力,而是依賴 Fetch API 或 axios 三方庫提供請求能力,useQuery() 做的就是提供響應數據存儲和請求狀態的包裝。

在講解了 useQuery() 基礎使用后,我們介紹了圍繞 useQuery() API 的一些核心內容,包括:

  1. 錯誤重試(Retries)機制:默認 3 次
  2. 數據緩存(Query Key):默認 5 分鐘
  3. 過期時間(Stale Time):默認即過期

最后 staleTime 與 cacheTime 之間的區別是:staleTime 決定數據的新鮮度,cacheTime 則用于指定緩存數據。

值得注意的是,“緩存 5 秒鐘”并不是說數據獲取后,過 5 秒鐘就刪掉了,而是說查詢緩存在不活躍(inactive)或未使用(unused),5 秒鐘后數據就被垃圾回收器回收了。

當然限于篇幅,useQuery() 還有內容沒講,這個我們留在下次再說。

好了,希望本文的講解能夠對你有所幫助。感謝閱讀,再見。

參考資料

[1]概述了 React Query 是什么: https://juejin.cn/post/7378015213348257855

[2]官方定義: https://tanstack.com/query/v3/docs/framework/react/reference/useQuery

[3]不再監聽 focus 事件: https://tanstack.com/query/v5/docs/framework/react/guides/migrating-to-v5#window-focus-refetching-no-longer-listens-to-the-focus-event

[4]意外多出來的后臺請求: https://github.com/TanStack/query/pull/4805

[5]cacheTime 選項改名: https://tanstack.com/query/v5/docs/framework/react/guides/migrating-to-v5#rename-cachetime-to-gctime

責任編輯:武曉燕 來源: 寫代碼的寶哥
相關推薦

2021-01-19 05:29:41

代碼Git 工作流

2021-03-26 10:48:14

代碼語言提交

2021-10-11 08:21:23

@Valuespringspring框架

2022-01-25 12:14:39

面試try-catch代碼

2021-09-01 05:41:03

Promise CLI項目

2022-09-14 12:00:51

React路由庫前端

2024-05-16 20:48:23

ReactReact 19React 編譯器

2021-09-28 12:25:30

數據庫

2021-06-11 06:45:32

SQL結構化語言

2022-05-09 08:01:23

countdistinctMySQL

2022-09-27 10:52:25

Pythonprint函數

2021-05-27 07:54:21

JavaStateAQS

2022-09-21 10:45:42

局域網Mesh網絡結構

2017-06-19 08:30:35

大數據數據可視化報表

2018-12-11 12:58:20

CPU散熱器鰭片

2025-03-28 10:39:17

C++宏定義語言

2018-06-08 16:48:09

PythonQQ機器人

2021-11-10 15:39:40

手機旗艦機中端機

2019-11-26 14:11:52

互聯網裁員員工
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 97热在线| 国产亚洲精品一区二区三区 | 国产精品久久久乱弄 | 色综合久久久 | 一级看片免费视频囗交动图 | 欧美日韩在线视频一区 | 欧美日韩综合一区 | 久久久精品网 | 99精品国产在热久久 | 国产日韩欧美激情 | 中文字幕一区二区三区四区 | 欧美日韩综合视频 | 中文字幕一区在线观看视频 | 男女深夜网站 | 精品欧美一区二区在线观看欧美熟 | 日韩成人在线电影 | 欧美精品第一页 | 一级a爱片性色毛片免费 | 午夜激情影院 | wwww.xxxx免费 | 亚洲欧美中文日韩在线v日本 | 国产精品美女久久久久久不卡 | 精品免费 | 欧美一区二区在线免费观看 | 日韩中文字幕网 | 在线中文视频 | 国产精品一区二区无线 | 国产日韩欧美激情 | 久久久一区二区三区四区 | 欧美一区二区免费 | 青青草网 | 青青久草 | 欧美a在线| 成人免费在线观看 | 一区网站| 国产欧美精品区一区二区三区 | 97色在线观看免费视频 | 欧美在线不卡 | 中国免费黄色片 | 国产成人网 | 秋霞av国产精品一区 |