redux tookit - rtk query的简单使用

redux tookit - rtk query

官网:https://redux-toolkit.js.org/rtk-query/overview

rtk query@reduxjs/toolkit 包中的的一个可选插件,其体系结构在内部使用redux。rtk query 是一个强大的数据获取和缓存工具,RTK Query 是一个强大的数据获取和缓存工具。它旨在简化在 Web 应用程序中加载数据的常见情况,无需自己手动编写数据获取和缓存逻辑。极大简化代码。

RTK Query 包含以下API:

  • createApi

    RTK query功能的核心。允许定义一组endpoints来描述如何从一系列endpoints检索数据,包括如何获取和转换该数据的配置。经验法则:每个基本URL使用一个API slice。

  • fetchbasQuery

    fetch 的一个小包装,旨在简化请求。

  • 可以作为 Provider 使用如果你还没有redux store

  • setupListeners

    用于启用 refetchOnMount 和 refetchOnReconconnect 行为的实用程序

接下来我将介绍一下该工具的简单使用

引用 (可通过以下两种方式获得)

ts
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'

定义API slice

ts
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({ // 作为唯一key挂载到store reducerPath: 'rootApi', // 所有请求都以 https://fakeApi 这个开头 baseQuery: fetchBaseQuery({ baseUrl: 'https://fakeApi' }), // 代表对该服务器的操作和请求 endpoints: (builder) => ({ // builder.query<resType, reqParamType>, build.query 一般用于 GET 请求 // builder.mutation一般用于会改变数据库数据请求 比如POST请求 getPokemonByName: builder.query<Pokemon, string>({ query: (name) => `pokemon/${name}`, }), updatePokemon: builder.mutation<void, Pokemon>({ query: ({id, ...pathch}) => { url: `pokemon/${name}`, method: 'POST', body: patch }, }), }), }) // 为 `getPokemonByName` Query endpoint 导出自动生成的 hooks export const { useGetPokemonByNameQuery, useUpdatePokemonMutation } = pokemonApi

我一般会拆分开来使用,因为项目中接口请求不止一个,可以把定义API slice 放在一个文件,请求可以通过 injectEndpoints 把需要的请求放入。

roote-api.ts

ts
import {createApi, fetchBaseQuery} from '@reduxjs/toolkit/query/react'; // Define a service using a base URL and expected endpoints const rootApi = createApi({ // 作为唯一key挂载到store reducerPath: 'rootApi', // 所有请求都以 https://fakeApi 这个开头 baseQuery: fetchBaseQuery({ baseUrl: 'https://fakeApi' }), // 代表对该服务器的操作和请求 endpoints: () => ({}), }); export default rootApi;

features/api/pokemon-api.js

ts
import rootApi from '@/store/root-api'; const pokemonApi = rootApi.injectEndpoints({ endpoints: builder => ({ // builder.query<resType, reqParamType>, build.query 一般用于 GET 请求 // builder.mutation一般用于会改变数据库数据请求 比如POST请求 getPokemonByName: builder.query<Pokemon, string>({ query: (name) => `pokemon/${name}`, }), updatePokemon: builder.mutation<void, Pokemon>({ query: ({id, ...pathch}) => { url: `pokemon/${name}`, method: 'POST', body: patch }, }), }), }); export const { useGetPokemonByNameQuery, useUpdatePokemonMutation } = pokemonApi

配置store

API slice 还包含一个自动生成的Redux slice reducer (rootApi.reducer) 和一个自定义中间件(rootApi.middleware),这里的rootApi是我上面定义的 API slice

store.js

ts
import postsReducer from '../features/posts/postsSlice' import usersReducer from '../features/users/usersSlice' import notificationsReducer from '../features/notifications/notificationsSlice' import { apiSlice } from '../features/api/apiSlice' export default configureStore({ reducer: { posts: postsReducer, users: usersReducer, notifications: notificationsReducer, [routApiSlice.reducerPath]: rootApi.reducer }, middleware: getDefaultMiddleware => getDefaultMiddleware().concat(rootApi.middleware) })

在组件中使用hooks

每个生成的query hooks 都会返回一个包含多个字段的对象,包括:

  • data: 来自服务器的实际响应内容,收到响应之前,该字段将是 undefined
  • isLoading: boolean类型, 代笔此hooks当前是否正在向服务器发出第一次请求。(注意:如果参数更改以请求不同的数据,isLoading将保持为false)
  • isFetching: boolean类型,此hooks当前是否正在向服务器发出任何请求。
  • isSuccess: boolean类型, 此hooks 是否已成功请求并有可用的缓存数据
  • isError: boolean类型, 指最后一个请求是否有错误
  • error: 一个 serialized 错误对象
tsx
import * as React from 'react' import { useGetPokemonByNameQuery, useUpdatePokemonMutation } from './features/api/pokemon-api' 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') const [trigger, { data, error, isLoading }] = useUpdatePokemonMutation() const updatePokenmon = (data) => { trigger(data); } // render UI based on data and loading state }