Skip to main content

React Query

Why React Query ?

React 在 data fetch 上是較不方便的,不依靠第三方工具來處理資料的話,以下的功能需經過複雜的處理才有辦法達成:global state、success or error status、cache、background updating…。

為什麼不應該在 React 中直接使用 useEffect 從 API 中直接獲取數據

React Query V3 簡易說明及使用

What’s React Query? React Query 是一個很適合用於 React Hook 的 Library 他可以幫我們取得、同步、更新、緩存我們的遠端數據,可以更好的處理 Server 端的 State

原理:

透過 Promise、Async、Await 來處理異步數據

優點:

  • 幫助我們減少複雜的程式碼,用較少的 React 查詢邏輯來代替
  • 不用擔心如何連接新的 Server State
  • 節省及提高效能
  • 可以處理麻煩的 Cache (Cache Time 預設 5min 回收)
  • 不用進行配置

簡易使用方式

Provider 建置

import { QueryClient, QueryClientProvider } from 'react-query';

const queryClient = new QueryClient();
const App = () => {
return {
<QueryClientProvider client={queryClient}>
<div className="app">
{/*... pages here */}
</div>
</QueryClientProvider>
}
}

Basic Usage

useQuery 所需要的參數有兩個,一個是鍵值名稱,另一個則是 data fetchingfunction

import { useQuery } from "react-query";

// Step 1: 建立基本查詢的function getUsers
const getUsers = async () => {
const response = await fetch("XXX.url.com/users");
const data = await response.data();
return data;
};

// Step 2:
// 使用 useQuery, getUsers 放到第二個參數
// 除了拿到 data 以外 還有提供 isLoading isError isSuccess 等各種狀態
const { isLoading, isError, isSuccess, data } = useQuery(["users"], getUsers);

機制

如果 fetch 的 data 有問題(網址打錯、提供錯誤參數等),React Query 會自動 retry(refetch)三次,三次都取得不到 data 的話則會顯示 error。 另外,React Query 也有 Window Refocus Refetching 的功能,意思是當瀏覽器切換到其他分頁再切換回來時,會重新 Fetch data。

React Query Dev Tools

React Query 也有提供開發管理工具 React Query Dev Tools

import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";

const queryClient = new QueryClient();

ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools />
</QueryClientProvider>
</React.StrictMode>,
document.getElementById("root")
);

React Query Keys

import { useQuery } from "tanstack/react-query";

// 建立基本查詢的function getUsers
// 把querykey 帶入
const getUsers = async ({ querykey }) => {
const response = await fetch(`https://xxx`, querykey[1]);
return response.json();
};

// 設定 queryKey...
const [id, setId] = useState(0);

const { isLoading, isError, isSuccess, data, isFetching } = useQuery(
["users", id],
getUsers,
{
//更多設定...
staleTime: 0, // 從Server 獲取資料後過時的長度
enable: false, //是否啟用, 如果有相依某api, 可以等待某api回來以後再來觸發
refetchOnWindowFocus: false, // 離開視窗 再回來並不會再打一次 request
cacheTime: 1000, // 一秒後清除cache資料
retry: 10, // 重試次數
retryDelay: 1000, // 等待1000 ms 在重試
}
);
  • staleTime 是從 Server 獲取資料過時之前的時間長度。 React Query 中的預設值是 staleTime: 0 - 這表示您的資料立即過時!
  • cacheTime 是從快取中刪除非活動資料之前的時間長度。 React Query 中的預設值為 cacheTime: 300000 - 即 5 分鐘。

useMutation

useMutation(addTodo, {
onMutate: (variables) => {
// A mutation is about to happen!

// Optionally return a context containing data to use when for example rolling back
return { id: 1 };
},
onError: (error, variables, context) => {
// An error happened!
console.log(`rolling back optimistic update with id ${context.id}`);
},
onSuccess: (data, variables, context) => {
// Boom baby!
},
onSettled: (data, error, variables, context) => {
// Error or success... doesn't matter!
},
});

Invalidation from Mutations

// 使用invalidateQueries 重新refetch資料
queryClient.invalidateQueries("key");

Tutorial Video:

Reference: