Home > database >  Middleware for RTK-Query API at reducerPath "api" has not been added to the store
Middleware for RTK-Query API at reducerPath "api" has not been added to the store

Time:10-01

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?

enter image description here

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;
  • Related