Skip to main content

React Query 的緩存機制 - stale time vs. cache (gc) time

stale time:決定資料「保鮮期」多久

  • stale time 之內,資料都是「新鮮」的
  • 在保鮮期內,不同的元件只要使用 同一組 query key 進行 query,都會從 cache 返回資料,不會重新 fetch API
  • 保鮮期過後,並不會馬上主動 refetch API,而有特定時機的 trigger
    • refetchOnMount:使用該 query 的元件 mount 時,進行 refetch
    • refetchOnWindowFocus:(當畫面上有使用該 query 的元件)使用者點擊其他分頁後,再重新 focus 分頁時,進行 refetch
    • refetchOnReconnect:(當畫面上有使用該 query 的元件)重新連線時,進行 retch
    • 重要:trigger 後,refetch 是背景進行的,react query 會盡可能先從 cache 中返回舊資料(如果可用),同時 refetch,完畢後再返回新資料,並且 re-render
      • 這個設定可以增進使用者體驗,減少割裂感
  • useQuery 的預設:stale time = 0,沒有保鮮期,所以 refetch 會比較頻繁

來點例子

export function useUserInfo() {
const isLogin = useSelector(isLoginSelector);
const query = useQuery({
queryKey: [API_SERVICES.GET_USER_INFO],
queryFn: () => authApi.getUserInfo(),
select: (result) => result?.data,
enabled: isLogin,
});

return {
query,
data: query.data,
status: query.status,
isError: query.isError,
isSuccess: query.isSuccess,
isPending: query.isPending,
};
}

假設:

選單有兩個元件可以前往

  • Profile 元件有使用 useUserInfo
  • Dashboard 元件有使用 useUserInfo

staleTime 為 0

  • 進入 Dashboard,fetch api
  • 點擊選單進入 Profile,會重新 fetch api (refetchOnMount
  • 點擊瀏覽器其他分頁,再重新點擊回來,會重新 fetch api (refetchOnWindowFocus
  • 關掉 wifi,再重新開啟,會重新 fetch api (refetchOnReconnect

staleTime 為 0 秒,但 refetchOnMount 為 false

  • 進入 Dashboard,fetch api
  • 點擊選單進入 Profile,使用緩存,不重新 fetch api (refetchOnMount
  • 點擊瀏覽器其他分頁,再重新點擊回來,會重新 fetch api (refetchOnWindowFocus

staleTime 為 15 秒

  • 進入 Dashboard,fetch api
  • 進入 Dashboard 後的 15 秒內,點擊選單進入 Profile,使用緩存,不重新 fetch api
  • 到其他元件,再重回 Profile,因為 15 秒到了,所以重新 fetch ap
  • 重新 fetch API 後的 15 秒內,馬上點擊瀏覽器其他分頁,再重新點擊回來,使用緩存,不重新 fetch api
  • 重新 fetch API 後 15 秒,點擊瀏覽器其他分頁,再重新點擊回來,會重新 fetch api

cache (gc) time:決定資料「保留」多久

note:當某個 query,不被任何已 mount 的元件所使用,會變成 inactive 狀態

cacheTime (現在名為 gcTime):當某個 query 變為 inactive 時,cache 會在 query store 保留多久,預設為 5 分鐘

來點例子

選單有三個元件可以前往

  • Profile 元件有使用 useUserInfo
  • Dashboard 元件有使用 useUserInfo
  • OtherPage 元件 沒有 使用 useUserInfo

gcTime 為 15 秒,staleTime 為 0

round 1

  • 進入 Dashboard,fetch api
  • 進入 OtherPage,現在沒有任何元件掛載 query,故 dev tool 可以看到 inactive query 數量為 1,也代表還在 cache 保留時間內
  • 進入 OtherPage 15 秒內,切換 Dashboard,雖然背景正在 fetching api,但直接先從 cache 返回資料,Dashboard 不會有空白情況

round 2

  • 進入 Dashboard,fetch api
  • 進入 OtherPage,現在沒有任何元件掛載 query,故 dev tool 可以看到 inactive = 1,也代表還在 cache 保留時間內
  • 等待 15 秒過後,dev tool 中 inactive query 數量從 1 變回 0(因為該 query 也被清除了),過了 cache 保留時間,cache 已被清除
  • 切換 Dashboard,背景正在 fetching api,但因為 cache 已被清除了,所以 fetching 時是空白的