RTK Query 概述
- 什么是 RTK Query 以及它解决了什么问题
- RTK Query 中包含哪些 API
- 基本的 RTK Query 使用方法
RTK Query 是一款功能强大的数据获取和缓存工具。它旨在简化 Web 应用程序中加载数据的常见情况,无需手动编写数据获取和缓存逻辑。
RTK Query 是 Redux Toolkit 包中可选的附加组件,其功能建立在 Redux Toolkit 中其他 API 的基础之上。
要了解如何使用 RTK Query,请参阅 Redux 核心文档网站上的完整"Redux Essentials" 教程。
如果您更喜欢视频课程,您可以在 Egghead 上免费观看 RTK Query 创建者 Lenz Weber-Tronic 的这门 RTK Query 视频课程,或者直接查看第一课。
动机
Web 应用程序通常需要从服务器获取数据以进行显示。它们通常还需要更新这些数据,将这些更新发送到服务器,并将客户端上的缓存数据与服务器上的数据保持同步。由于需要实现当今应用程序中使用的其他行为,这变得更加复杂。
- 跟踪加载状态以显示 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,这些 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
的一个小包装器,旨在简化请求。旨在作为createApi
中用于大多数用户的推荐baseQuery
。<ApiProvider />
: 如果您还没有 Redux 商店,可以使用它作为Provider
。setupListeners()
: 用于启用refetchOnMount
和refetchOnReconnect
行为的实用程序。
捆绑包大小
RTK Query 会为您的应用程序捆绑包大小添加一个固定的单次数量。由于 RTK Query 建立在 Redux Toolkit 和 React-Redux 之上,因此添加的大小会根据您是否已经在应用程序中使用它们而有所不同。估计的 min+gzip 捆绑包大小为
- 如果您已经在使用 RTK:RTK Query 约 9kb,hooks 约 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 切片 reducer 和一个自定义中间件,用于管理订阅生命周期。这两者都需要添加到 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)
在组件中使用钩子
最后,从 API 切片中将自动生成的 React 钩子导入到您的组件文件中,并在您的组件中使用任何需要的参数调用这些钩子。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 钩子。
在RTK Query 使用指南部分中,您可以找到有关以下主题的信息:查询数据、使用变异向服务器发送更新、流式缓存更新等等。
在示例页面中,您可以找到可运行的 CodeSandboxes,这些 CodeSandboxes 演示了以下主题:使用 GraphQL 进行查询、身份验证,甚至将 RTK Query 与其他 UI 库(如 Svelte)一起使用。