React Query
React Query 是一個很實用的 React 工具庫,專門用來處理後端資料的獲取、快取、同步和共享。它讓我們在開發資料驅動的應用程式時,可以更輕鬆地與伺服器進行溝通。React Query 能幫助你更有效率地管理應用程式中的資料,無論是從 API 獲取資料、管理資料的加載狀態,還是處理錯誤,都變得更加容易。
React Query 的核心概念
- Query:用來取得資料。每個 Query 都會有一個獨特的 key,這個 key 是用來識別和快取資料的。舉例來說,你可以使用
useQuery
這個 hook 來發送 API 請求並取得資料。 - Mutation:用來修改資料。當你需要發送 POST、PUT、DELETE 等請求時,可以使用
useMutation
來處理。Mutation 通常適合在表單提交的情境下使用。 - Query Client:負責管理和存儲 Query 狀態的實體。透過這個實體,你可以設定全域配置、手動觸發資料重新獲取、清除快取等等。
- Cache(快取):React Query 會自動管理資料的快取,你可以設定快取時間,以及是否需要重新獲取快取中的資料。
- 背景同步:React Query 支援在背景中自動同步資料,這樣一來,當資料發生變化時,應用程式就會自動更新顯示。
Query
Query 是 React Query 中用來取得資料的核心概念。你可以使用 useQuery
這個 hook 來發送 API 請求並取得資料。
主要的參數有:
queryKey
:用來識別和快取資料的 key。當queryKey
發生變化時,React Query 會重新發送 API 請求。queryFn
:用來發送 API 請求的 函數。
Query 狀態
在 Query 中,狀態可以分成兩大類分別是 status
和 fetchStatus
。
-
status
:用來表示資料的獲取狀態,有以下幾種值:isPending
或status === 'pending'
- 尚無資料isSuccess
或status === 'success'
- 查詢成功isError
或status === 'error'
- 查詢失敗
-
fetchStatus
:用來表示**queryFn
的執行狀態**,有多種情況會觸發,例如:第一次獲取資料、重新獲取資料 (refetch)、對快取資料進行背景更新 (stale-while-revalidate)、手動觸發重新獲取資料等,fetchStatus
有以下幾種值:isIdle
或fetchStatus === 'idle'
- 尚無發送請求isFetching
或fetchStatus === 'fetching'
- 正在發送請求isPaused
或fetchStatus === 'paused'
- 請求暫停
範例
function Todos() {
const {
status,
data: todos,
error,
isFetching,
} = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});
if (status === 'pending') {
return <span>Loading...</span>;
}
if (status === 'error') {
return <span>Error: {error.message}</span>;
}
return (
<>
{isFetching && <div>Refreshing...</div>}
<div>
{todos.map((todo) => (
<Todo key={todo.id} todo={todo} />
))}
</div>
</>
);
}
Mutation
Mutation 是 React Query 中用來修改資料的核心概念。當你需要發送 POST、PUT、DELETE 等請求時,可以使用 useMutation
來處理。
主要的參數有:
mutationFn
:用來發送 API 請求的函數。
Mutation 狀態
Mutation 有以下幾種狀態:
isIdle
或status === 'idle'
- mutation 當前處於空閒狀態或處於全新/重置狀態isPending
或status === 'pending'
- mutation 正在運行isError
或status === 'error'
- mutation 遇到錯誤isSuccess
或status === 'success'
- mutation 成功
Mutation Side Effects
Mutation 也支援 side effects,你可以在 mutation 完成後執行一些額外的操作。
範例
useMutation({
mutationFn: 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!
},
});