React Query 的緩存機制 - stale time vs. cache (gc) time
stale time:決定資料「保鮮期」多久
- stale time 之內,資料都是「新鮮」的
- 在保鮮期內,不同的元件只要使用 同一組 query key 進行 query,都會從 cache 返回資料,不會重新 fetch API
- 保鮮期過後,並不會馬上主動 refetch API,而有特定時機的 trigger
refetchOnMount
:使用該 query 的元件 mount 時,進行 refetchrefetchOnWindowFocus
:(當畫面上有使用該 query 的元件)使用者點擊其他分頁後,再重新 focus 分頁時,進行 refetchrefetchOnReconnect
:(當畫面上有使用該 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 時是空白的