• 19 【RTK Query】


    19 【RTK Query】

    1.目前前端常见的发起 ajax 请求的方式

    • 1、使用原生的ajax请求
    • 2、使用jquery封装好的ajax请求
    • 3、使用fetch发起请求
    • 4、第三方的比如axios请求
    • 5、angular中自带的HttpClient

    就目前前端框架开发中来说我们在开发vuereact的时候一般都是使用fetchaxios自己封装一层来与后端数据交互,至于angular肯定是用自带的HttpClient请求方式,但是依然存在几个致命的弱点,

    • 1、对当前请求数据不能缓存,
    • 2、一个页面上由多个组件组成,但是刚好有遇到复用相同组件的时候,那么就会发起多次ajax请求

    📢 针对同一个接口发起多次请求的解决方法,目前常见的解决方案

    • 1、使用axios的取消发起请求,参考文档
    • 2、vue中还没看到比较好的方法
    • 3、在rect中可以借用类似react-query工具对请求包装一层
    • 4、对于angular中直接使用rxjs的操作符shareReplay

    2.RTK Query 概述

    RTK不仅帮助我们解决了state的问题,同时,它还为我们提供了RTK Query用来帮助我们处理数据加载的问题。RTK Query是一个强大的数据获取和缓存工具。在它的帮助下,Web应用中的加载变得十分简单,它使我们不再需要自己编写获取数据和缓存数据的逻辑。

    rtk-queryredux-toolkit里面的一个分之,专门用来优化前端接口请求,目前也只支持在react中使用。

    RTK Query 是一个强大的数据获取和缓存工具。它旨在简化在 Web 应用程序中加载数据的常见情况,无需自己手动编写数据获取和缓存逻辑

    RTK Query 是一个包含在 Redux Toolkit 包中的可选插件,其功能构建在 Redux Toolkit 中的其他 API 之上。

    Web应用中加载数据时需要处理的问题:

    1. 根据不同的加载状态显示不同UI组件
    2. 减少对相同数据重复发送请求
    3. 使用乐观更新,提升用户体验
    4. 在用户与UI交互时,管理缓存的生命周期

    这些问题,RTKQ都可以帮助我们处理。首先,可以直接通过RTKQ向服务器发送请求加载数据,并且RTKQ会自动对数据进行缓存,避免重复发送不必要的请求。其次,RTKQ在发送请求时会根据请求不同的状态返回不同的值,我们可以通过这些值来监视请求发送的过程并随时中止。

    我们将 createAsyncThunkcreateSlice 一起使用,在发出请求和管理加载状态方面仍然需要进行大量手动工作。我们必须创建异步 thunk,发出实际请求,从响应中提取相关字段,添加加载状态字段,在 extraReducers 中添加处理程序以处理 pending/fulfilled/rejected 情况,并实际编写正确的状态更新。

    在过去的几年里,React 社区已经意识到 “数据获取和缓存” 实际上是一组不同于 “状态管理” 的关注点。虽然你可以使用 Redux 之类的状态管理库来缓存数据,但用例差异较大,因此值得使用专门为数据获取用例构建的工具。

    RTK Query 在其 API 设计中添加了独特的方法:

    • 数据获取和缓存逻辑构建在 Redux Toolkit 的 createSlicecreateAsyncThunk API 之上
    • 由于 Redux Toolkit 与 UI 无关,因此 RTK Query 的功能可以与任何 UI 层一起使用
    • API 请求接口是提前定义的,包括如何从参数生成查询参数和转换响应以进行缓存
    • RTK Query 还可以生成封装整个数据获取过程的 React hooks ,为组件提供 dataisFetching 字段,并在组件挂载和卸载时管理缓存数据的生命周期
    • RTK Query 提供“缓存数据项生命周期函数”选项,支持在获取初始数据后通过 websocket 消息流式传输缓存更新等用例
    • 我们有从 OpenAPI 和 GraphQL 模式生成 API slice 代码的早期工作示例
    • 最后,RTK Query 完全用 TypeScript 编写,旨在提供出色的 TS 使用体验

    📢 rtk-query的使用环境,必须是react版本大于 17,可以使用hooks的版本,因为使用rtk-query的查询都是hooks的方式,如果你项目简单redux都未使用到,本人不建议你用rtk-query,可能直接使用axios请求更加的简单方便。

    3.基础开发流程

    后面这些案例后端接口返回格式都是

    {
        
        "code":200,
        "data":[]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 创建一个store文件夹
    • 创建一个index.ts做为主入口
    • 创建一个festures/api文件夹用来装所有的API Slice
    • 创建一个sudentApiSlice.js文件,并导出简单的加减方法

    3.1 定义 API Slice

    使用 RTK Query,管理缓存数据的逻辑被集中到每个应用程序的单个“API Slice”中。就像每个应用程序只有一个 Redux 存储一样,我们现在有一个Slice 用于 所有 我们的缓存数据。

    我们将从定义一个新的 sudentApiSlice.js 文件开始。由于这不是特定于我们已经编写的任何其他“功能”,我们将添加一个新的 features/api/ 文件夹并将 sudentApiSlice.js 放在那里。让我们填写 API Slice 文件,然后分解里面的代码,看看它在做什么:

    features/api/sudentApiSlice.js

    // 从特定于 React 的入口点导入 RTK Query 方法
    import {
        createApi, fetchBaseQuery } from '@reduxjs/toolkit/dist/query/react'
    // 上面这个引入的会自动创建钩子
    // import { createApi } from '@reduxjs/toolkit/query'
    
    // 定义我们的单个 API Slice 对象
    //createApi() 用来创建RTKQ中的API对象
    // RTKQ的所有功能都需要通过该对象来进行
    // createApi() 需要一个对象作为参数
    export const sudentApiSlice = createApi({
       
      reducerPath: 'studentApi', // Api的标识,不能和其他的Api或reducer重复
      // 指定查询的基础信息,发送请求使用的工具
      baseQuery: fetchBaseQuery({
       
        // 我们所有的请求都有以 “/api 开头的 URL
        baseUrl: 'http://localhost:8080/api',
      }),
      // “endpoints” 代表对该服务器的操作和请求
      endpoints: builder => ({
       
        // `getStudents` endpoint 是一个返回数据的 “Query” 操作
        getStudents: builder.query({
       
          // 请求的 URL 是“/api/all/student”
          query: () => '/all/student',
        }),
      }),
    })
    
    // Api对象创建后,对象中会根据各种方法自动的生成对应的钩子函数
    // 通过这些钩子函数,可以来向服务器发送请求
    // 钩子函数的命名规则 getStudents --> useGetStudentsQuery
    export const {
        useGetStudentsQuery } = sudentApiSlice
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    上例是一个比较简单的Api对象的例子,我们来分析一下,首先我们需要调用createApi()来创建Api对象。这个方法在RTK中存在两个版本,一个位于@reduxjs/toolkit/dist/query下,一个位于@reduxjs/toolkit/dist/query/react下。react目录下的版本会自动生成一个钩子,方便我们使用Api。如果不要钩子,可以引入query下的版本,当然我不建议你这么做。

    createApi()需要一个配置对象作为参数,配置对象中的属性繁多,我们暂时介绍案例中用到的属性:

    reducerPath

    用来设置reducer的唯一标识,主要用来在创建store时指定action的type属性,如果不指定默认为api。

    baseQuery

    用来设置发送请求的工具,就是你是用什么发请求,RTKQ为我们提供了fetchBaseQuery作为查询工具,它对fetch进行了简单的封装,很方便,如果你不喜欢可以改用其他工具,这里暂时不做讨论。

    fetchBaseQuery

    简单封装过的fetch调用后会返回一个封装后的工具函数。需要一个配置对象作为参数,baseUrl表示Api请求的基本路径,指定后请求将会以该路径为基本路径。配置对象中其他属性暂不讨论。

    endpoints

    Api对象封装了一类功能,比如学生的增删改查,我们会统一封装到一个对象中。一类功能中的每一个具体功能我们可以称它是一个端点。endpoints用来对请求中的端点进行配置。

    endpoints是一个回调函数,可以用普通方法的形式指定,也可以用箭头函数。回调函数中会收到一个build对象,使用build对象对点进行映射。回调函数的返回值是一个对象,Api对象中的所有端点都要在该对象中进行配置。

    对象中属性名就是要实现的功能名,比如获取所有学生可以命名为getStudents,根据id获取学生可以命名为getStudentById。属性值要通过build对象创建,分两种情况:

    查询:build.query({})

    增删改:build.mutation({})

    例如:

    getStudents: builder.query({
       
      // 请求的 URL 是“/api/all/student”
      query: () => '/all/student',
    }),
    
    • 1
    • 2
    • 3
    • 4
    • 5

    先说query,query也需要一个配置对象作为参数。配置对象里同样有n多个属性,现在直说一个,query方法。注意不要搞混两个query,一个是build的query方法,一个是query方法配置对象中的属性,这个方法需要返回一个子路径,这个子路径将会和baseUrl拼接为一个完整的请求路径。比如:getStudets的最终请求地址是:

    http://localhost:8080/api + /all/student = http://localhost:8080/api/all/student
    
    • 1

    可算是介绍完了,但是注意了这个只是最基本的配置。RTKQ功能非常强大,但是配置也比较麻烦。不过,熟了就好了。

    上例中,我们创建一个Api对象studentApi,并且在对象中定义了一个getStudents方法用来查询所有的学生信息。如果我们使用react下的createApi,则其创建的Api对象中会自动生成钩子函数,钩子函数名字为useXxxQuery或useXxxMutation,中间的Xxx就是方法名,查询方法的后缀为Query,修改方法的后缀为Mutation。所以上例中,Api对象中会自动生成一个名为useGetStudentsQuery的钩子,我们可以获取并将钩子向外部暴露。

    export const {
       useGetStudentsQuery} = studentApi;
    
    • 1
    • 2

    3.2 配置 Store

    我们现在需要将 API Slice 连接到我们的 Redux 存储。我们可以修改现有的 store.js 文件,将 API slice 的 cache reducer 添加到状态中。此外,API slice 会生成需要添加到 store 的自定义 middleware。这个 middleware 必须 被添加——它管理缓存的生命周期和控制是否过期。

    store/index.js

    import {
        configureStore } from '@reduxjs/toolkit'
    import {
        sudentApiSlice } from './features/api/sudentApiSlice'
    
    // configureStore创建一个redux数据
    const store = configureStore({
       
      
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    11-Spring架构源码分析-IoC 之注册解析的 BeanDefinitions
    智源发布最强开源可商用中英文语义向量模型 BGE,超越同类模型,解决大模型制约问题
    CalBioreagents超全Id 蛋白兔单克隆抗体,助力科研
    黑马点评-异步秒杀实现
    智慧校园建设的进阶之路
    【高项笔记】No.3 网络接入技术和网络规划与设计
    [强网杯 2022]factor有感
    小商品公众号微信店铺搭建的作用是什么
    Nginx网站服务-LNMP
    实用电脑软件
  • 原文地址:https://blog.csdn.net/DSelegent/article/details/127998478