LOADING

MiniKano的小窝


 

Redux之RTKQ的使用

Redux之RTKQ的使用

RTKQ 是 React Toolkit Query 的简写
RTKQ可以很方便的为我们实现Ajax API的管理

安装RTKQ

RTKQ目前已经集成在RTK工具包内,我们只需要安装RTK即可

# NPM
npm install @reduxjs/toolkit

# Yarn
yarn add @reduxjs/toolkit

编写一个基本的API store

首先在src目录内创建一个store文件夹,在其中创建index.js文件

import { configureStore} from "@reduxjs/toolkit";
import { setupListeners } from "@reduxjs/toolkit/dist/query";
import studentApi from './studentApi'
const store = configureStore({
    //将api对象配置到reducer里
    reducer: {
        [studentApi.reducerPath]: studentApi.reducer
    },
    //中间件 可以扩展store (RTKQ缓存)
    middleware: getDefaultMiddleware => getDefaultMiddleware().concat(studentApi.middleware)
})

setupListeners(store.dispatch)//设置以后才可以支持 refetchOnFocus refetchOnReconnect
export default store

store创建studentApi文件夹,在其中创建index.js

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/dist/query/react";
//创建Api对象
//RTKQ的所有功能都需要该对象才能进行
const studentApi = createApi({
  reducerPath: "studentApi", //api标识,不能和其他apireducer重复
  //fetchBaseQuery其实就是fetch套壳
  baseQuery: fetchBaseQuery({
    baseUrl: "http://localhost:8888/api/",
  }), //用来指定查询的基础信息,发送请求使用的工具
  tagTypes: ['student'],//指定API中标签的类型
  endpoints(build) {
    return {
      // 这些请求都带缓存
      getStudents: build.query({
        query() {
          //指定请求的子路径
          return "students";
        },
        //处理返回的数据
        transformResponse(baseQueryReturnValue) {
          return baseQueryReturnValue.data
        },
        providesTags: [{
          type: 'student',
          id: 'list'
        }]
      }),
      getStudentById: build.query({
        query(id) {
          return `students/${id}`
        },
        transformResponse(baseQueryReturnValue) {
          return baseQueryReturnValue.data
        },
        // keepUnusedDataFor: 0,//设置数据的缓存时间s(默认60秒)

        //也可以写成回调函数的形式,三个参数,res,err和query中的参数(id)
        //返回一个数组
        //这样写可以细化列表请求,添加数据的时候,老数据还是可以保留缓存,不至于刷新整个列表
        providesTags: (result, err, id) => {
          return [{ type: 'student', id }]
        }
      }),
      deleteStudent: build.mutation({//改动需要使用mutation
        query(id) {
          //发送的不是get请求,需要返回一个对象
          return {
            url: `students/${id}`,
            method: 'delete'
          }
        },
        invalidatesTags: [{
          type: 'student',
          id: 'list'
        }]
      }),
      addStudent: build.mutation({
        query(stu) {
          return {
            url: 'students',
            method: 'post',
            body: {
              data: stu
            }
          }
        },
        //这个设置之后,数组中的tag只要有api中的providesTags匹配,就会使providesTags所在的api数据缓存失效,从而可以达到从新获取数据的目的
        //这个非常好用!数据变动后可以自动获取数据!
        invalidatesTags: [{
          type: 'student',
          id: 'list'
        }]
      }),
      updateStudent: build.mutation({
        query(stu) {
          return {
            url: `students/${stu.id}`,
            method: 'put',
            body: {
              data: stu.attributes
            }
          }
        },
        //别忘了返回的是一个数组,是可以传多个tag的
        invalidatesTags: (result, err, stu) => {
          return [{ type: 'student', id: stu.id }, { type: "student", id: 'list' }]
        }
      })
    };
  }, //endpotints 需要一个对象作为返回值,指定
});
// api对象创建完毕后,对象中会根据各种方法去自动生成对应的构造函数
// 通过这些钩子函数,就可以来向服务器发送请求
//钩子函数命名规则 getStudents --> useGetStudentsQuery

export const { useGetStudentsQuery, useGetStudentByIdQuery, useDeleteStudentMutation, useAddStudentMutation, useUpdateStudentMutation } = studentApi;
export default studentApi;

store创建studentContext文件夹,在其中创建index.js

import React from "react";
const studentContext = React.createContext({
    getData: () => { }
})
export default studentContext

修改src/App.jsx

import "./App.css";
import StudentList from "./components/StudentList/StudentList";
import studentContext from "./store/studentContext";
import { useGetStudentsQuery } from "./store/studentApi";
function App() {
  //使用自定义钩子
  const { data, isSuccess, isLoading, refetch } = useGetStudentsQuery(null, {
    //useQuer可以接收一个对象作为第二个参数,通过该对象可以对请求进行配置
    // selectFromResult: (result) => {
    //   if (result.data) {
    //   return result.data;
    //   }
    // },
    pullingInterval: 0, //设置轮询时间间隔 单位ms 为0则不允许
    skip: false, //设置是否跳过当前请求 默认false
    //false表示正常缓存
    refetchOnMountOrArgChange: false, //是否在挂载/参数变化时候重新加载数据 可以传时间,和bool值
    //是否在重新获取焦点时重载数据(页面标签页切换)//需要store使用setupListeners(store.dispatch)
    // refetchOnFocus: true,
    //是否在重新连接网络时重载数据
    // refetchOnReconnect: false,
  });
  const getDataHandler = () => {
    console.log('get');
    refetch();
  };
  return (
    <studentContext.Provider
      value={{
        getData: getDataHandler,
      }}
    >
      <button onClick={() => refetch()}>加载数据</button>
      <div className="App">
        {!isLoading && isSuccess ? (
          <StudentList data={data}></StudentList>
        ) : (
          "加载中。。"
        )}
      </div>
    </studentContext.Provider>
  );
}

export default App;

修改src/index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    {/* //使用store */}
    <App />
  </Provider>
);

其中Student组件和studentform组件是为了展示列表数据的组件,这里没有进行详细展示

总之,一个简单的RTKQ API 就搭建好了

点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注