【问题标题】:Middleware for RTK-Query API at reducerPath "api" has not been added to the storereducerPath "api" 的 RTK-Query API 中间件尚未添加到商店
【发布时间】:2021-12-02 16:10:40
【问题描述】:

我正在创建一个反应原生应用程序,我收到了这个警告。 reducerPath "api" 处的 RTK-Query API 中间件尚未添加到商店中。 自动缓存收集、自动重新获取等功能将不可用。

我看到我的 api 没有被重新获取。

这是我的 rootReducer.ts 文件

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;

这是我的 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-jrtec-soyaig',
  onError: 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>();

这是我正在使用 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

我在我的页面上使用这个钩子来获取数据

  const { data, error, isLoading: isLoadingGetStories } = useGetStoriesQuery(page);

这是我收到的信息。你能告诉我我的代码有什么问题吗?

enter image description here

【问题讨论】:

    标签: react-native rtk-query


    【解决方案1】:

    您忘记添加 API 中间件。见文档here.

    【讨论】:

    • 看起来他的 store.ts 里已经有这个了。
    【解决方案2】:

    我能够让持久状态和 rtk-query 一起工作来改变我的 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
        ),
    });
    

    对于持久状态,可以以这种形式读取状态

      const isConnected2Internet = useSelector((state: RootState) => state.persistedReducer.notification.isConnected2Internet);
    

    【讨论】:

    • 您也可以将 RTK-Query 切片添加到您的 persistConfigblacklist,这样您就不需要额外的嵌套
    • 感谢@phry,这是一个更好的解决方案
    【解决方案3】:

    这是使用黑名单的更好解决方案

    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',
          onError: 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;
    

    【讨论】:

    • 比什么好?为什么?
    • 你好@DavidBuck 我首先尝试添加reducer:{ [storiesApi.reducerPath]: storiesApi.reducer,persistedReducer },但我有一个resetAppAction,它没有重新启动rtk缓存。使用黑名单更好。
    猜你喜欢
    • 2022-11-11
    • 2017-10-14
    • 1970-01-01
    • 2023-03-28
    • 2014-02-16
    • 1970-01-01
    • 2021-10-22
    • 2021-10-04
    • 2021-08-16
    相关资源
    最近更新 更多