RTK Query 概觀
- RTK Query 是什麼,以及它解決了什麼問題
- RTK Query 中包含哪些 API
- RTK Query 的基本用法
RTK Query 是一個強大的資料擷取和快取工具。它旨在簡化網頁應用程式中載入資料的常見案例,讓您無需親自撰寫資料擷取和快取邏輯。
RTK Query 是Redux Toolkit 套件中包含的選用附加元件,其功能建立在 Redux Toolkit 中其他 API 之上。
若要了解如何使用 RTK Query,請參閱 Redux 核心文件網站上的完整「Redux Essentials」教學。
如果您偏好影片課程,您可以在 Egghead 免費觀看 Lenz Weber-Tronic(RTK Query 的創建者)的這堂 RTK Query 影片課程,或在此處查看
動機
網頁應用程式通常需要從伺服器擷取資料才能顯示。它們通常也需要更新資料、將更新傳送至伺服器,並讓用戶端上的快取資料與伺服器上的資料保持同步。由於需要實作現今應用程式中使用的其他行為,這變得更加複雜
- 追蹤載入狀態以顯示 UI 載入指示器
- 避免對相同資料重複要求
- 樂觀更新以讓 UI 感覺更快
- 在使用者與 UI 互動時管理快取生命週期
Redux 核心一直非常精簡 - 由開發人員撰寫所有實際邏輯。這表示 Redux 從未包含任何內建功能來協助解決這些使用案例。Redux 文件已教導一些常見的模式,用於在要求生命週期中發送動作以追蹤載入狀態和要求結果,而 Redux Toolkit 的 createAsyncThunk
API 則設計為抽象化典型模式。然而,使用者仍必須撰寫大量的 reducer 邏輯來管理載入狀態和快取資料。
在過去幾年中,React 社群已了解到「資料擷取和快取」實際上與「狀態管理」是不同的關注事項。雖然你可以使用 Redux 等狀態管理函式庫來快取資料,但使用案例差異很大,因此值得使用專門為資料擷取使用案例建置的工具。
RTK Query 汲取了其他開創資料擷取解決方案的工具的靈感,例如 Apollo Client、React Query、Urql 和 SWR,但為其 API 設計增添了獨特的方法
- 資料擷取和快取邏輯建構於 Redux Toolkit 的
createSlice
和createAsyncThunk
API 之上 - 由於 Redux Toolkit 與 UI 無關,因此 RTK Query 的功能可與任何 UI 層搭配使用
- API 端點會預先定義,包括如何從參數產生查詢參數以及轉換回應以進行快取
- RTK Query 也可以產生 React hooks,它封裝了整個資料擷取流程,提供
data
和isLoading
欄位給元件,並在元件掛載和卸載時管理快取資料的生命週期 - RTK Query 提供「快取項目生命週期」選項,可啟用使用案例,例如在擷取初始資料後透過 websocket 訊息串流快取更新
- 我們有從 OpenAPI 和 GraphQL 架構產生 API 片段的早期工作範例
- 最後,RTK Query 完全以 TypeScript 編寫,旨在提供絕佳的 TS 使用體驗
包含的內容
API
RTK Query 包含在核心 Redux Toolkit 套件的安裝中。可透過以下兩個進入點取得
import { createApi } from '@reduxjs/toolkit/query'
/* React-specific entry point that automatically generates
hooks corresponding to the defined endpoints */
import { createApi } from '@reduxjs/toolkit/query/react'
RTK Query 包含這些 API
createApi()
:RTK Query 功能的核心。它允許您定義一組「端點」,描述如何從後端 API 和其他非同步來源擷取資料,包括如何擷取和轉換資料的設定。在多數情況下,您應該在每個應用程式中使用一次,原則上採用「每個基本 URL 一個 API 區段」的方式。fetchBaseQuery()
:fetch
的小型包裝,旨在簡化要求。預計作為建議的baseQuery
,供多數使用者在createApi
中使用。<ApiProvider />
:可用作Provider
,如果您尚未擁有 Redux 儲存體。setupListeners()
:用於啟用refetchOnMount
和refetchOnReconnect
行為的工具程式。
套件大小
RTK Query 會為您的應用程式套件大小新增一個固定的單次金額。由於 RTK Query 建立在 Redux Toolkit 和 React-Redux 之上,因此新增的大小會根據您是否已在應用程式中使用這些而有所不同。估計的 min+gzip 套件大小為
- 如果您已經使用 RTK:RTK Query 約 9kb,掛鉤約 2kb。
- 如果您尚未使用 RTK
- 不含 React:RTK+依賴項+RTK Query 為 17 kB
- 含 React:19kB + React-Redux,這是對等依賴項
新增其他端點定義應該只會根據 endpoints
定義中的實際程式碼增加大小,通常僅為幾個位元組。
RTK Query 中包含的功能很快就能彌補新增的套件大小,而且消除手寫資料擷取邏輯應該會顯著改善多數有意義應用程式的程式碼大小。
基本用法
建立 API 區段
RTK Query 包含在核心 Redux Toolkit 套件的安裝中。可透過以下兩個進入點取得
import { createApi } from '@reduxjs/toolkit/query'
/* React-specific entry point that automatically generates
hooks corresponding to the defined endpoints */
import { createApi } from '@reduxjs/toolkit/query/react'
對於與 React 的典型用法,首先匯入 createApi
並定義一個「API 區段」,其中列出伺服器的基本 URL 以及我們想要與之互動的端點
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import type { Pokemon } from './types'
// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
}),
}),
})
// Export hooks for usage in functional components, which are
// auto-generated based on the defined endpoints
export const { useGetPokemonByNameQuery } = pokemonApi
設定儲存體
「API 切片」也包含自動產生的 Redux 切片還原器和管理訂閱生命週期的自訂中間件。這兩者都需要新增到 Redux 儲存庫
import { configureStore } from '@reduxjs/toolkit'
// Or from '@reduxjs/toolkit/query/react'
import { setupListeners } from '@reduxjs/toolkit/query'
import { pokemonApi } from './services/pokemon'
export const store = configureStore({
reducer: {
// Add the generated reducer as a specific top-level slice
[pokemonApi.reducerPath]: pokemonApi.reducer,
},
// Adding the api middleware enables caching, invalidation, polling,
// and other useful features of `rtk-query`.
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(pokemonApi.middleware),
})
// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch)
在元件中使用 Hooks
最後,將自動產生的 React hooks 從 API 切片匯入元件檔案,並在元件中呼叫 hooks,並提供任何需要的參數。RTK Query 會在掛載時自動擷取資料、在參數變更時重新擷取、在結果中提供 {data, isFetching}
值,並在這些值變更時重新呈現元件
import * as React from 'react'
import { useGetPokemonByNameQuery } from './services/pokemon'
export default function App() {
// Using a query hook automatically fetches data and returns query values
const { data, error, isLoading } = useGetPokemonByNameQuery('bulbasaur')
// Individual hooks are also accessible under the generated endpoints:
// const { data, error, isLoading } = pokemonApi.endpoints.getPokemonByName.useQuery('bulbasaur')
// render UI based on data and loading state
}
進一步資訊
請參閱 RTK Query 快速入門教學,了解如何將 RTK Query 新增到使用 Redux Toolkit 的專案、設定具有端點定義的「API 切片」,以及如何在元件中使用自動產生的 React hooks。
RTK Query 使用指南區段 提供有關主題的資訊,例如 查詢資料、使用突變將更新傳送至伺服器、串流快取更新 等更多資訊。
範例頁面 提供可執行 CodeSandboxes,展示主題,例如 使用 GraphQL 進行查詢、驗證,甚至 將 RTK Query 與其他 UI 函式庫(例如 Svelte)一起使用。