如何在RTK Query中缓存数据同时持久化历史数据到Redux Store?
解决RTK Query缓存数据同时保存历史记录的方案
方案一:使用RTK Query内置的onQueryStarted生命周期函数
这是最直接的方案,无需额外中间件,直接在API Slice的Endpoint配置中处理查询结果,同时不影响RTK Query的缓存逻辑。
实现步骤:
- 定义存储历史电压数据的Slice:
import { createSlice } from '@reduxjs/toolkit'; const voltageHistorySlice = createSlice({ name: 'voltageHistory', initialState: { history: [] }, reducers: { addVoltageHistory: (state, action) => { // 可选:限制历史记录长度,比如只保留最近100条 state.history = [...state.history, action.payload].slice(-100); } } }); export const { addVoltageHistory } = voltageHistorySlice.actions; export default voltageHistorySlice.reducer;
- 在RTK Query API Slice中给
getVoltageEndpoint添加onQueryStarted回调:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { addVoltageHistory } from './voltageHistorySlice'; const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/api' }), endpoints: (builder) => ({ getVoltage: builder.query({ query: () => '/voltage', // 拦截查询成功的结果 async onQueryStarted(args, { dispatch, queryFulfilled }) { try { // 等待查询完成拿到数据 const { data } = await queryFulfilled; // 分发action将数据存入历史记录Slice dispatch(addVoltageHistory({ value: data.voltage, timestamp: Date.now() })); } catch (err) { // 可选:处理查询失败的情况 console.error('电压数据获取失败:', err); } } }) }) }); export const { useGetVoltageQuery } = api; export default api;
方案二:使用RTK Listener Middleware监听RTK Query的成功Action
如果需要更灵活的全局监听逻辑(比如同时处理多个Endpoint的结果),可以用Listener Middleware,但要注意监听的是RTK Query自动生成的成功Action类型,而非Hook本身。
实现步骤:
- 配置Listener Middleware并添加监听逻辑:
import { configureStore } from '@reduxjs/toolkit'; import { api } from './apiSlice'; import voltageHistoryReducer from './voltageHistorySlice'; import { createListenerMiddleware } from '@reduxjs/toolkit'; import { addVoltageHistory } from './voltageHistorySlice'; const listenerMiddleware = createListenerMiddleware(); // 监听getVoltage查询成功的Action listenerMiddleware.startListening({ actionCreator: api.endpoints.getVoltage.matchFulfilled, effect: async (action, listenerApi) => { // action.payload就是RTK Query返回的电压数据 const voltageData = action.payload; // 分发action保存到历史记录 listenerApi.dispatch(addVoltageHistory({ value: voltageData.voltage, timestamp: Date.now() })); } }); export const store = configureStore({ reducer: { [api.reducerPath]: api.reducer, voltageHistory: voltageHistoryReducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware() .concat(api.middleware) .prepend(listenerMiddleware.middleware) });
方案对比
- 方案一:代码简洁,与Endpoint绑定紧密,适合单个Endpoint的专属处理逻辑,无需额外配置中间件。
- 方案二:灵活性更高,可统一处理多个Endpoint的结果,或添加复杂条件判断逻辑,但需要额外配置Listener Middleware。
两种方案都能保证RTK Query正常处理缓存,同时将数据持久化到自定义Store Slice中,满足查看当前电压和绘制历史波动图的需求。
内容的提问来源于stack exchange,提问作者user101289
相关产品推荐
相关产品推荐

