I understand that RTK Query signifies a shift in thinking from Redux store / state management, and the general paradigm is that you use the RTK Query endpoint anytime you need data, and rely on it to manage cache and state rather than slices / thunks etc.
However, I have an endpoint (defined as an RTK query endpoint) that pulls voltage data for a device on a hardware system. I want to know that voltage at any given point in time, but I also want to maintain some history so I can draw a graph showing the voltage fluctuation.
My thinking is that I can intercept the query results in the RTK Query api slice, and use a normal reducer action to put the data into the store. However, since the RTK query isn't a component I can't use a reducer hook in there. I still think there's got to be a way from the RTK Query API slice to directly interact with the store, but I haven't found any docs on this.
The second route I was thinking was using a middleware to intercept the query action, do whatever is needed with the data, and store it. However, the middleware examples I've found all relate to using traditional redux toolkit slice actions, not RTK query endpoints, so this throws errors:
listenerMiddleware.startListening({
actionCreator: useGetVoltageQuery, /// <-- this is an endpoint in RTK Query API slice, not a slice action
effect: async (action, listenerApi) => {
// Run whatever additional side-effect-y logic you want here
console.log('GOT HERE')
// Can cancel other running instances
listenerApi.cancelActiveListeners()
// Run async logic
/*const data = await fetchData()
// Pause until action dispatched or state changed
if (await listenerApi.condition(matchSomeAction)) {
// Use the listener API methods to dispatch, get state,
// unsubscribe the listener, start child tasks, and more
listenerApi.dispatch(updateVoltage(listenerApi.))
}*/
},
})
Is there a recommended way to manipulate data from RTK query and persist it to the store, as well as handling the query results in the normal RTK cache?
Is there a recommended way to manipulate data from RTK query and persist it to the store, as well as handling the query results in the normal RTK cache?
Yes, you can create a state slice that defines a case reducer that matches when an endpoint call is fulfilled.
Example:
export const api = createApi({
reducerPath: "api",
baseQuery,
endpoints: (build) => ({
getVoltage: build.query({
// ...
}),
// ...
}),
});
const voltageSlice = createSlice({
name: "voltage",
initialState,
reducers: {
// ...regular case reducers
},
extraReducers: (builder) => {
builder.addMatcher(
api.endpoints.getVoltage.matchFulfilled,
(state, action) => {
// update the state accordingly
state.history.push(action.payload);
}
);
},
});
An alternative is to dispatch an action to the store when the getVoltage
query is fulfilled.
Example:
export const api = createApi({
reducerPath: "api",
baseQuery,
endpoints: (build) => ({
getVoltage: build.query({
// ...
onQueryStarted: async (arg, queryApi) => {
const { dispatch, queryFulfilled } = queryApi;
const { data } = await queryFulfilled;
dispatch(someStateSlice.addVoltage(data));
},
}),
// ...
}),
});
const voltageSlice = createSlice({
name: "voltageState",
initialState,
reducers: {
// ...regular case reducers
addVoltage: (state, action) => {
// update the state accordingly, example
state.history.push(action.payload);
},
},
});