Table of contents
Open Table of contents
前言
在公司內部的分享會中,分享了 React Query 的使用方法。在這裡將他整理成文章,方便之後遇到問題可以複習。
介紹
什麼是 React Query
React Query 是什麼? 在官方文件的第一頁寫了
React Query is often described as the missing data-fetching library for React, but in more technical terms, it makes fetching, caching, synchronizing and updating server state in your React applications a breeze.
所以可以知道的是,React 本身缺少了 data fetching 的工具,而 React Query 可以彌補這件事情。
用比較技術性的話語來講,React Query 可以 “輕鬆” 的達成 fetching、caching、synchronizing 與 updating server state 這些功能。
當我們搜尋 React Query 的時候,會出現以下兩種文件。
在 2022 年的 7 月,React Query 推出的第四個版本。並稱為 TankStack Query。
那麼會有這個改動,是因為他想要遵循 Framework Agnostic 這個規範。
Framework Agnostic
Framework Agnostic 的意思是,工具不依賴特定的框架或平台,可以在多個環境中運行。它可以讓開發者選擇適合他們的框架,而不是被限制於特定的框架。就
像原本的 react query 他只能在 react 中使用。改名叫 tankquery 後,官方文件的左側就可以選擇其他的框架,目前也支援 Vue、Svelte、Solid 這三個框架。
那麼也遵循 Framework Agnostic 的工具,還包括了 vite 跟 typescript。
v3 與 v4 的差異
文件裡面提及非常多的更新,那這邊我紀錄文件中的前四項更新。
- update imports to @tanstack/react-query
- update all query keys to be arrays
- The idle state has been removed
- new API for useQueries
第一個更新就是 import 的改變
第二的更新就是 query key 變成只能帶入 array,在 v3 中是可以帶入 string 或是 array。
第三個更新是 status: idle 在 v4 中就將他移除,原因是因為在 v4 中新增了 fetchStatus 的參數。
所以目前 status 只有三個狀態。
loading
error
success
fetchStatus 也只有三種
fetching
pause
idle
第四個更新是可以使用 useQueries
這個參數,可以一次打多個 api 。
使用方法
QueryClient
在整個專案的進入點 (ex. src/index.js) 加上
- QueryClient
- QueryClientProvider
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
},
});
function App() {
return (
<QueryClientProvider client={queryClient} contextSharing={true}>
<Todos />
</QueryClientProvider>
);
}
useQuery
- useQuery 在取得資料時使用
- 第三種方法的 status 是一個 string,有三種狀態
loading
error
success
useQuery 可以有很多種寫法,這邊我大致分為三種。
寫法一跟二是透過解構,進而取得 data 跟 status。
寫法三是透過宣告變數,再使用變數取存取值。
個人會比較推薦寫法三,因為當一個頁面要發多個 api 時,data 就會出現命名衝突。大多時候都還需要重新命名,所以不如一開始就宣告變數,就可以省去很多麻煩,程式碼也會更好閱讀。
import { useQuery } from "@tanstack/react-query";
function App() {
const getPostFn = () =>
axios.get("http://localhost:8888/posts").then(res => res.data);
// 寫法一
const { isLoading, error, data, isFetching, refetch } = useQuery({
queryKey: ["post"],
queryFn: getPostFn,
});
if (isLoading) {
return "Loading...";
}
// 寫法二
const { status, data } = useQuery({
queryKey: ["post"],
queryFn: getPostFn,
});
if (status === "isLoading") {
return "isLoading...";
}
// 寫法三
const post = useQuery({
queryKey: ["post"],
queryFn: () => getPostFn(),
});
if (post.isLoading) {
return "Loading...";
}
}
useMutation
- useMutation 在修改資料時使用
refech()
是 useQuery 的 api。當我們送出一筆資料後,他可以在 Success 之後,幫我們重新發一個 Get 的 api,達到畫面更新的效果。
import { useMutation } from "@tanstack/react-query";
function App() {
const postFn = newPost => axios.post("http://localhost:8888/posts", newPost);
const mutation = useMutation({
mutationFn: postFn,
onSuccess: () => {
// useQuery
refetch();
},
});
return (
<>
{mutation.isError ? (
<div>An error occurred: {mutation.error.meesage}</div>
) : null}
{mutation.isSuccess ? <div>Post added!</div> : null}
<button
onClick={() => {
mutation.mutate({ id: crypto.randomUUID(), title: "test" });
}}
></button>
</>
);
}
比較
接下來會談一些 api 的比較,避免再開發的時候誤用。
status vs fetchStatus
status
可以知道當前的資料狀態。fetchStatus
可以知道當前的請求狀態,如果需要知道請求是否正在運行,則需使用fetchStatus
。
cacheTime vs staleTime
CacheTime
指的是資源的快取時間。- 表示在這個時間之後,資源就不再是有效的。
- Default 5 min
StaleTime
指的是資源的陳舊時間。- 設定結果可以被視為「過期」的時間長度。
- 舉例來說,如果 staleTime 設為 10 分鐘。意思就是在 10 分鐘內,useQuery 將不會再次發出請求以獲取數據。如果數據在 10 分鐘內發生變化,則必須等到下一次使用者對頁面進行操作或等到
staleTime
到期後,才會發出新的請求以獲取最新數據。 - Default 0 min
如果想要 data 保持最新,可以設置較短的 staleTime
,並且在過期之後立即重新發出請求以獲取最新 data。
如果我們要保持最大的緩存使用效率,則可以設置較長的 cacheTime
以保留 data 在緩存中較長的時間。
設置好 cacheTime
與 staleTime
的優點是,在請求之後可以大大減少 API 的請求次數,減少 request,提高頁面加載速度,避免頁面一直出現 Loading 的樣式,提高使用者體驗。