You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+RTK注册功能出现invalidatesTags未定义的TypeError错误

错误原因分析:TypeError: Cannot read properties of undefined (reading 'invalidatesTags')

错误信息

TypeError: Cannot read properties of undefined (reading 'invalidatesTags')
    at calculateProvidedByThunk (buildThunks.ts:629:1)
    at handler (invalidationByTags.ts:31:1)
    at index.ts:120:1
    at index.ts:102:1
    at index.ts:102:1
    at index.js:20:1
    at immutableStateInvariantMiddleware.ts:253:1
    at dispatch (redux.js:691:1)
    at createAsyncThunk.ts:682:1
    at step (index.ts:4:1)

问题根源

1. RTK Query端点嵌套定义错误

在authApi中,你将register mutation嵌套在了login mutation内部,setNewPassword嵌套在了resetPassword mutation内部。RTK Query要求每个endpoint必须是builder直接返回的顶级属性,这种嵌套结构会导致RTK无法正确识别和注册这些mutation,触发内部逻辑时找不到对应的配置项,从而抛出invalidatesTags读取错误。

2. 多个API实例reducerPath重复

authApi和adminApi的reducerPath都设置为"api",RTK Query要求每个createApi实例的reducerPath必须唯一,否则两个API的状态会在Redux store中相互覆盖,引发内部状态处理的异常。

修复步骤

第一步:修正authApi的端点定义

将嵌套的mutation改为顶级端点:

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const authApi = createApi({
  reducerPath: "authApi", // 修改为唯一的reducerPath
  baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_API_ROOT_URL }),
  endpoints: (builder) => ({
    login: builder.mutation({
      query: (body) => ({
        url: "/users/login",
        method: "post",
        body,
      }),
    }),
    // 改为顶级mutation
    register: builder.mutation({
      query: (body) => ({
        url: "/users/register",
        method: "post",
        body,
      }),
    }),
    resetPassword: builder.mutation({
      query: (body) => ({
        url: "/resetPassword",
        method: "PATCH",
        body,
      }),
    }),
    // 改为顶级mutation,参数调整为单个对象(RTK mutation仅支持单个参数)
    setNewPassword: builder.mutation({
      query: ({ body, token }) => ({
        url: `/resetPassword/${token}`,
        method: "PATCH",
        body,
      }),
    }),
  }),
});

export const {
  useLoginMutation,
  useRegisterMutation,
  useResetPasswordMutation,
  useSetNewPasswordMutation,
} = authApi;

第二步:修正adminApi的reducerPath及请求头配置

将adminApi的reducerPath改为唯一值,同时修复prepareHeaders的返回逻辑:

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const adminApi = createApi({
  reducerPath: "adminApi", // 修改为唯一的reducerPath
  baseQuery: fetchBaseQuery({
    baseUrl: process.env.REACT_APP_API_ROOT_URL,
    prepareHeaders: (headers, { getState }) => {
      const token = getState().auth.JWT;
      if (token) {
        headers.set("authorization", `Bearer ${token}`);
      }
      return headers; // 确保始终返回headers对象,避免无token时返回undefined
    },
  }),
  tagTypes: ["Categories", "Products", "Tva", "Product"],
  endpoints: (builder) => ({
    // 其余端点代码保持不变
    getCategoriesAdmin: builder.query({
      query: () => "/categories/getAllAdmin",
      providesTags: ["Categories", "Products"],
    }),
    getProductsAdmin: builder.query({
      query: () => "/products/getAllAdmin",
      providesTags: ["Categories", "Products"],
    }),
    getOneProductAdmin: builder.query({
      query: (id) => `/products/getOneAdmin/${id}`,
    }),
    getTvaAdmin: builder.query({
      query: () => "/TVA/getAllAdmin",
      providesTags: ["Tva"],
    }),
    addProduct: builder.mutation({
      query: (body) => ({
        url: "/products/createOne",
        method: "post",
        body,
      }),
      invalidatesTags: ["Categories", "Products"],
    }),
    updateProductPut: builder.mutation({
      query: (o) => ({
        url: `/products/updateOnePut/${o.id}`,
        method: "PUT",
        body: o.body,
      }),
      invalidatesTags: ["Categories", "Products"],
    }),
    updateProductPatch: builder.mutation({
      query: (o) => ({
        url: `/products/updateOnePatch/${o.id}`,
        method: "PATCH",
        body: o.body,
      }),
      invalidatesTags: ["Categories", "Products"],
    }),
  }),
});

export const {
  useGetCategoriesAdminQuery,
  useGetTvaAdminQuery,
  useGetProductsAdminQuery,
  useAddProductMutation,
  useUpdateProductPutMutation,
  useUpdateProductPatchMutation,
  useGetOneProductAdminQuery,
} = adminApi;

第三步:更新Store中的reducer配置

对应修改store中的reducer键名,匹配新的reducerPath:

import { configureStore, combineReducers } from "@reduxjs/toolkit";
import authReducer from "./slices/authSlice";
import adminReducer from "./slices/adminSlice";
import shopReducer from "./slices/shopSlice";
import { persistReducer, persistStore } from "redux-persist";
import thunk from "redux-thunk";
import storage from "redux-persist/lib/storage";
import { shopApi } from "./api/shopApi";
import { authApi } from "./api/authApi";
import { adminApi } from "./api/adminApi";

const persistConfig = {
  key: "root",
  storage,
};

const rootReducer = combineReducers({
  auth: authReducer,
  admin: adminReducer,
  shop: shopReducer,
  [authApi.reducerPath]: authApi.reducer,
  [shopApi.reducerPath]: shopApi.reducer,
  [adminApi.reducerPath]: adminApi.reducer,
});

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) => {
    const allMiddleware = [
      authApi.middleware,
      shopApi.middleware,
      adminApi.middleware,
      thunk,
    ];
    return getDefaultMiddleware({ serializableCheck: false }).concat(
      ...allMiddleware
    );
  },
});

export const persistor = persistStore(store);

验证

修复后,调用registerUser时将不再触发该错误,同时所有API的状态会被正确隔离,避免互相干扰。

内容的提问来源于stack exchange,提问作者Marie-Lou Le Jan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:10:36