I am creating a react native app and I am getting this warning. Middleware for RTK-Query API at reducerPath "api" has not been added to the store. Features like automatic cache collection, automatic refetching etc. will not be available.
I see my api is not been refetching.
This is my rootReducer.ts file
import {combineReducers} from '@reduxjs/toolkit';
import { storiesApi } from 'src/services/storiesService'
const appReducer = combineReducers({
[storiesApi.reducerPath]: storiesApi.reducer,
});
const rootReducer = (state, action) => {
if (action.type === 'RESET_APP') {
state = undefined;
}
return appReducer(state, action);
};
export const resetAppAction = () => dispatch => {
console.log('Reset Redux Store');
dispatch({type: 'RESET_APP'});
};
export default rootReducer;
This is my store.ts file
import { useDispatch as useReduxDispatch, useSelector as useReduxSelector } from 'react-redux';
import type { TypedUseSelectorHook } from 'react-redux';
import type { ThunkAction } from 'redux-thunk';
import type { Action } from '@reduxjs/toolkit';
import { configureStore } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query/react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist"
import { encryptTransform } from 'redux-persist-transform-encrypt';
import thunk from 'redux-thunk';
import { ENABLE_REDUX_DEV_TOOLS } from 'src/constants';
import rootReducer from './rootReducer';
import { storiesApi } from 'src/services/storiesService'
const encryptor = encryptTransform({
secretKey: 'my-super-secret-key-jrtec-soyaig',
one rror: function (error) {
// Handle the error.
},
});
const persistConfig = {
// Root
key: 'root',
// Storage Method (React Native)
storage: AsyncStorage,
timeout: null,
transforms: [encryptor],
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
devTools: ENABLE_REDUX_DEV_TOOLS,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}).concat(
thunk,
storiesApi.middleware
),
});
// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch)
export const persistor = persistStore(store);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export type AppThunk = ThunkAction<void, RootState, null, Action<string>>;
export const useSelector: TypedUseSelectorHook<RootState> = useReduxSelector;
export const useDispatch = () => useReduxDispatch<AppDispatch>();
This is my service I am using axios storiesService.ts
import { createApi, BaseQueryFn } from '@reduxjs/toolkit/query/react'
import { AxiosRequestConfig, AxiosError } from 'axios'
import responseCamelizerAxios from 'src/lib/axiosInstance';
const API_STORIES = '/api/stories/users/';
export interface IPost {
createdAt: string;
department: string;
description: string;
image: string[];
likeStatus: boolean;
likes: number;
logo: string;
organization: string;
pk: string
title: string
}
interface IListResponse {
currentPage: number;
pageSizeNews: number;
results: IPost[]
totalNews: number;
totalPages: number;
}
export interface IChangeLikesResponse {
data: {
stories: {
pk: number;
like_active: boolean;
},
}
}
export interface IBodyChangeLikes {
postId: number;
likeStatus: boolean;
}
const axiosBaseQuery = (
{ baseUrl }: { baseUrl: string } = { baseUrl: '' }
): BaseQueryFn<
{
url?: string
method: AxiosRequestConfig['method']
body?: AxiosRequestConfig['data']
},
unknown,
unknown
> =>
async ({ url='', method, body }) => {
try {
const result = await responseCamelizerAxios({ url: baseUrl url, method, data: body })
console.log('result', result);
return { data: result.data }
} catch (axiosError) {
// console.log('axiosError', axiosError);
// console.log('axiosError', axiosError.response?.status);
let err = axiosError as AxiosError
return {
error: { status: err.response?.status, data: err.response?.data },
}
}
}
export const storiesApi = createApi({
baseQuery: axiosBaseQuery({ baseUrl: API_STORIES }),
endpoints: (build) => ({
getStories: build.query<IListResponse, number | void>({
query: (page = 1) => ({ url: `?page=${page}`, method: 'get' }),
}),
changeLikes: build.mutation<IChangeLikesResponse, IBodyChangeLikes>({
query: ({postId, likeStatus}: IBodyChangeLikes ) => ({
method: 'post',
body: {
data: {
stories: {
pk: postId,
like_active: likeStatus,
},
},
}
}),
}),
}),
})
export const { useGetStoriesQuery, useChangeLikesMutation } = storiesApi
I am using on my page this hook to get data
const { data, error, isLoading: isLoadingGetStories } = useGetStoriesQuery(page);
This is the message I have. Can you please tell me what is wrong with my code?
CodePudding user response:
I was able to have persisted state and rtk-query working together changing my conconfigureStore
export const store = configureStore({
reducer: {
[storiesApi.reducerPath]: storiesApi.reducer,
persistedReducer
},
devTools: ENABLE_REDUX_DEV_TOOLS,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}).concat(
thunk,
storiesApi.middleware
),
});
and state can be read in this form for persisted states
const isConnected2Internet = useSelector((state: RootState) => state.persistedReducer.notification.isConnected2Internet);
CodePudding user response:
This is a better solution using a blacklist
store.ts
import { useDispatch as useReduxDispatch, useSelector as useReduxSelector } from 'react-redux';
import type { TypedUseSelectorHook } from 'react-redux';
import type { ThunkAction } from 'redux-thunk';
import type { Action } from '@reduxjs/toolkit';
import { configureStore } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query/react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist"
import { encryptTransform } from 'redux-persist-transform-encrypt';
import thunk from 'redux-thunk';
import { ENABLE_REDUX_DEV_TOOLS } from 'src/constants';
import rootReducer from './rootReducer';
import { storiesApi } from 'src/services/storiesService'
const encryptor = encryptTransform({
secretKey: 'my-super-secret-key',
one rror: function (error) {
// Handle the error.
},
});
const persistConfig = {
key: 'root',
storage: AsyncStorage,
blacklist: [
storiesApi.reducerPath,
],
timeout: null,
transforms: [encryptor],
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
devTools: ENABLE_REDUX_DEV_TOOLS,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}).concat(
thunk,
storiesApi.middleware,
),
});
// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch)
export const persistor = persistStore(store);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export type AppThunk = ThunkAction<void, RootState, null, Action<string>>;
export const useSelector: TypedUseSelectorHook<RootState> = useReduxSelector;
export const useDispatch = () => useReduxDispatch<AppDispatch>();
rootReducer.ts
import { combineReducers } from '@reduxjs/toolkit';
import { reducer as authReducer } from 'src/redux/slices/auth';
import { reducer as storiesReducer } from 'src/redux/slices/stories';
import { storiesApi } from 'src/services/storiesService'
const appReducer = combineReducers({
auth: authReducer,
stories: storiesReducer,
[storiesApi.reducerPath]: storiesApi.reducer,
});
const rootReducer = (state, action) => {
if (action.type === 'RESET_APP') {
state = undefined;
}
return appReducer(state, action);
};
export const resetAppAction = () => dispatch => {
console.log('Reset Redux Store');
dispatch({ type: 'RESET_APP' });
};
export default rootReducer;