RTK Qurey+TypeScript基本使用(四):injectEndpoints和transformResponse

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


系列文章:
RTK Qurey+TypeScript基本使用(一):查询与添加数据
RTK Qurey+TypeScript基本使用(二):缓存刷新
RTK Qurey+TypeScript基本使用(三):修改本地缓存


前言

大型应用程序通常会将功能代码拆分到单独的包中,然后在首次使用该功能时按需延迟加载它们。

RTK Query 支持使用 apiSlice.injectEndpoints() 拆分请求接口。

// dataType/IPostState.tsx
import IReaction from "./IReaction";

interface IPostState {
    id: string;
    title: string;
    content: string;
    user: string;
    date: string;
}

export default IPostState;
// dataType/IUserState.tsx
interface IUserState {
    id: string;
    name: string
}

export default IUserState
// redux/apiSlice.tsx
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import IPostState from '../dataType/IPostState'

export const apiSlice = createApi({
    reducerPath: 'baseapi',
    baseQuery: fetchBaseQuery({ baseUrl: 'http://127.0.0.1:8780/fakeApi' }),
    endpoints: builder => ({
    	// 查询数据
        getPosts: builder.query<IPostState[], void>({
            query: () => '/posts',
            providesTags: ['Post']
        })
    })
})

export const { useGetPostsQuery } = apiSlice
// redux/store.tsx
import { configureStore } from '@reduxjs/toolkit'
import { apiSlice } from './apiSlice'

const store = configureStore({
    reducer: {
        [apiSlice.reducerPath]: apiSlice.reducer
    },
    middleware: getDefaultMiddleware => getDefaultMiddleware().concat(apiSlice.middleware)
})

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export default store;
// index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);

root.render(
  <Provider store={store}>
    <App />
  </Provider>

);

injectEndpoints的基本使用

我们使用 injectEndpoints() 对请求接口进行拆分

// redux/usersSlice.tsx
import IUserState from '../dataType/IUserState'
import { RootState } from "./store"


//注入接口
export const extendedApiSlice = apiSlice.injectEndpoints({
    endpoints: builder => ({
        getUsers: builder.query<IUserState[], void>({
            query: () => '/users',
        })
    })
})

export const { useGetUsersQuery } = extendedApiSlice

在其它组件调用 useGetUsersQuery 就可以获取对应的值

transformResponse的基本使用

假如现在我需要对返回的数据进行一定的处理

// redux/usersSlice.tsx
import { createEntityAdapter, EntityState } from '@reduxjs/toolkit'
import { apiSlice } from "./apiSlice"
import IUserState from '../dataType/IUserState'

// 范式化数据
const usersAdapter = createEntityAdapter<IUserState>()
const initialState = usersAdapter.getInitialState([])

//注入接口
export const extendedApiSlice = apiSlice.injectEndpoints({
    endpoints: builder => ({
        getUsers: builder.query<EntityState<IUserState>, void>({
            query: () => '/users',

            //该处理程序可以在缓存之前,提取或修改从服务器接收到的数据
            transformResponse: (response: IUserState[]) => {
                return usersAdapter.setAll(initialState, response)
            }
        })
    })
})

export const { useGetUsersQuery } = extendedApiSlice

这个时候我们再去调用 useGetUsersQuery 获取到的数据就不是从服务端获取的到的源数据了,而是在 transformResponse 中经过处理之后的数据

使用useSelector()来获取RTK query的数据

假如一份数据在程序中很多地方都要反复用到,而每个地方都调用 useGetUsersQuery 之类的方法来获取数据,显示的十分麻烦,而我们希望像redux那种使用 useSelector() 来获取数据
我们可以这样来实现

// redux/usersSlice.tsx
import { createEntityAdapter, createSelector, EntityState } from '@reduxjs/toolkit'
import { apiSlice } from "./apiSlice"
import IUserState from '../dataType/IUserState'
import { RootState } from "./store"

// 范式化数据
const usersAdapter = createEntityAdapter<IUserState>()
const initialState = usersAdapter.getInitialState([])

//注入接口
export const extendedApiSlice = apiSlice.injectEndpoints({
    endpoints: builder => ({
        getUsers: builder.query<EntityState<IUserState>, void>({
            query: () => '/users',

            //该处理程序可以在缓存之前提取或修改从服务器接收到的数据
            transformResponse: (response: IUserState[]) => {
                return usersAdapter.setAll(initialState, response)
            }
        })
    })
})

export const { useGetUsersQuery } = extendedApiSlice

// 获取请求的selector,就返回的查询请求
const selectUsersResult = extendedApiSlice.endpoints.getUsers.select()

//查出返回的查询请求中的数据,data为EntityState<IUserState>类型|undefined
const selectUsersData = createSelector(
    selectUsersResult,
    (usersResult) => usersResult.data
)

// 有结果出结果,没结果返回初始化的值
// 注意:?? initialState这个一定写啊,因为在请求查询没有完成之前,state中getUsers这个分支是没有值的
// 而这个时候恰好代码调用了,会导致报错,所有我们需要给它弄个默认值之类的
const selectUsers = (state: RootState) => selectUsersData(state) ?? initialState

//查询所有用户,查询特定id的用户
export const { selectAll: selectAllUsers, selectById: selectUserById } = usersAdapter.getSelectors(selectUsers)

index.tsx中手动调用getUsers,初始化数据

// index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './redux/store';
import { extendedApiSlice } from './redux/usersSlice';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);

//手动调用,初始化数据
store.dispatch(extendedApiSlice.endpoints.getUsers.initiate())

root.render(
  <Provider store={store}>
    <App />
  </Provider>

);

之后我们就可以其它组件调用 useSelector() 来获取数据了

// App.tsx
import React from 'react'
import { useSelector } from 'react-redux'
import { RootState } from './redux/store'
import { selectAllUsers, selectUserById } from './redux/usersSlice'

function App() {
  //查询所有数据
  let users = useSelector(selectAllUsers)
  console.log(users)

  //查询特定id的数据
  let user = useSelector((state: RootState) => selectUserById(state, '0'))
  console.log(user)

  return (
    <div>

    </div>
  )
}

export default App
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值