RTK 查询和 createSlice 额外减速器
我是 RTK 查询的新手,我目前正在观看一个教程,其中使用 ExtraReducers 将 RTK 查询数据存储在 redux 切片中。我试图将 RTK 查询数据存储在切片状态中,但无法做到。
import { createSlice } from "@reduxjs/toolkit";
import apiService from "../Services/serviceFeature";
const initialState = {
userInfo: null,
};
const userSlice = createSlice({
name: "user",
initialState,
reducers: {
userLogout: (state, action) => initialState,
},
extraReducers: (builder) => {
builder.addMatcher(
apiService.endpoints.authRegister.matchFulfilled,
(state, action) => (state.userInfo = action.payload)
);
builder.addMatcher(
apiService.endpoints.authLogin.matchFulfilled,
(state, action) => (state.userInfo = action.payload)
);
},
});
export const { userLogout } = userSlice.actions;
export default userSlice.reducer;
无论我做什么,状态都不会使用有效负载值进行更新,并且状态中的 userInfo 始终保持为空。
如果我像这样编写逻辑,一切都会奇迹般地正常工作,并且切片会存储来自 RTK 查询的值。
import { createSlice } from "@reduxjs/toolkit";
import apiService from "../Services/serviceFeature";
const initialState = null;
const userSlice = createSlice({
name: "user",
initialState,
reducers: {
userLogout: (state, action) => initialState,
},
extraReducers: (builder) => {
builder.addMatcher(
apiService.endpoints.authRegister.matchFulfilled,
(_, action) => action.payload
);
builder.addMatcher(
apiService.endpoints.authLogin.matchFulfilled,
(_, action) => action.payload
);
},
});
export const { userLogout } = userSlice.actions;
export default userSlice.reducer;
如果我在 extraReducers 中提到状态,即 (
state,action
),切片不会存储任何信息。devtools 始终显示
apiService/executeMutation/pending
,并且状态从未更新。一旦我删除状态并输入 _,请求就会得到满足,我就会得到数据。
如果我将切片写为 (
_,action
),切片会存储信息。为什么会这样?有什么想法吗?
编辑:从前端调度操作也不起作用。我尝试在切片中定义初始状态并登录(通过使用(
_,action
))。我从 addMatcher 获得结果,切片会使用新的 userInfo 进行更新。发生这种情况时,开发工具不会显示我定义的初始状态的任何痕迹。开发工具只显示用户数据而没有任何状态信息(如果代码是以后一种方式编写的)。尽管 initialState 具有 userInfo(
initialState:{userInfo:null>
,devtools 不会显示它。只显示 addMatcher 的结果(好像初始状态根本不存在)
尽管 initialState 具有 products:[] 和 name:'',但它似乎已在 redux Dev tools 中消失,而我只获得切片的名称和 api 结果(来自 addMatcher)
这是 RTK 查询代码
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
const apiService = createApi({
reducerPath: "fakeStore",
baseQuery: fetchBaseQuery({ baseUrl: "https://fakestoreapi.com/" }),
endpoints: (builder) => ({
getProd: builder.query({
query: () => ({
url: "products",
method: "GET",
}),
}),
}),
});
export default apiService;
export const { useGetProdQuery } = apiService;
商店
import { configureStore } from "@reduxjs/toolkit";
import prodReducer from "./prodSlice";
import apiService from "./service";
export const store = configureStore({
reducer: {
prod: prodReducer,
[apiService.reducerPath]: apiService.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(apiService.middleware),
});
问题是,如果我包含 addMatcher(因为 initialState 会消失,而 addMatcher 会永远保持加载状态),则无法通过说
state.products=action.payload
来更新切片中的状态。如果我只是说
(state,action)=>action.payload
,整个 initialState 就会消失,我会从添加匹配器中获取 api 值。
您不必将 rtk 查询的数据存储到任何地方。您只需在组件中导入
useGetProdQ​​uery
并像这样使用它
const {data, isLoading, isFetching, error} = useGetProdQ​​uery()
您缺少的是
isAnyOf()
,这是一个高阶函数,它返回一个函数,可用于检查某个操作是否与所提供的任何类型保护或操作创建者匹配。
您可以将代码更新为
import { createSlice, isAnyOf } from "@reduxjs/toolkit";
import apiService from "../Services/serviceFeature";
const initialState = {
userInfo: null,
};
const userSlice = createSlice({
name: "user",
initialState,
reducers: {
userLogout: (state, action) => initialState,
},
extraReducers: (builder) => {
builder.addMatcher(
isAnyOf(apiService.endpoints.authRegister.matchFulfilled), //updated
(state, action) => (state.userInfo = action.payload)
);
builder.addMatcher(
isAnyOf(apiService.endpoints.authLogin.matchFulfilled), //updated
(state, action) => (state.userInfo = action.payload)
);
},
});
export const { userLogout } = userSlice.actions;
export default userSlice.reducer;
从文档中查看此 rtk-query 示例 ,以获取有关用法的更多见解