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

RTK Query extraReducers初始化报错:Cannot read 'matchFulfilled'

问题描述

使用RTK与RTK Query做状态管理和数据获取,采用代码分割配置store时,应用初始化加载阶段,storeNew/authSliceNew.js中的extraReducers抛出错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'matchFulfilled')

临时 workaround:先注释authSliceNew.js里的extraReducers,启动应用后再取消注释,功能就能正常运行;但初始不注释就会触发上述报错。

相关代码文件:

storeNew/baseApi.js

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

export const baseApi = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: "api/" }),
  endpoints: () => ({}),
  tagTypes: ["User", "Budget"],
});

storeNew/authApiNew.js

import { baseApi } from "./baseApi";

const authApi = baseApi.injectEndpoints({
  endpoints: (builder) => ({
    registerUser: builder.mutation({
      query: (registerCredentials) => ({
        url: "account/register",
        method: "POST",
        body: { ...registerCredentials },
      }),
    }),
  }),
  overrideExisting: false,
});

export const {
  useRegisterUserMutation,
} = authApi;

storeNew/authSliceNew.js

import { createSlice } from "@reduxjs/toolkit";
import { baseApi } from "./baseApi";

const initialState = {
  isAuthenticated: false,
  register_success: false,
  feedback: null,
  feedbackType: null,
};

const authSlice = createSlice({
  name: "auth",
  initialState: initialState,
  reducers: {
    resetFeedback: (state) => {
      state.feedback = null;
      state.feedbackType = null;
    },
    resetRegisterSuccess: (state) => {
      state.register_success = false;
    },
  },

  extraReducers: (builder) => {
    builder.addMatcher(
      baseApi.endpoints.registerUser.matchFulfilled,
      (state) => {
        state.register_success = true;
        state.feedback = null;
        state.feedbackType = null;
      }
    );
  },
});

export const authActions = authSlice.actions;

export default authSlice;

storeNew/index.js

import { configureStore } from "@reduxjs/toolkit";
import { setupListeners } from "@reduxjs/toolkit/query";
import { baseApi } from "./baseApi";
import authSliceNew from "./authSliceNew";

const store = configureStore({
  reducer: {
    [baseApi.reducerPath]: baseApi.reducer,
    authNew: authSliceNew.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(baseApi.middleware),
});

setupListeners(store.dispatch);

export default store;
解决方案

这个问题是模块加载顺序导致的初始化时机问题:

  • authSliceNew.js直接从baseApi取registerUser endpoint,但这个endpoint是在authApiNew.js中注入到baseApi的
  • 初始化时,store/index.js先加载baseApi,再加载authSliceNew,此时authApiNew还没执行,baseApi.endpoints.registerUser还不存在,所以访问matchFulfilled会报错

推荐两种解决方法:

方法1:从authApiNew导出endpoint引用

修改authApiNew.js,把注入后的endpoint单独导出:

import { baseApi } from "./baseApi";

const authApi = baseApi.injectEndpoints({
  endpoints: (builder) => ({
    registerUser: builder.mutation({
      query: (registerCredentials) => ({
        url: "account/register",
        method: "POST",
        body: { ...registerCredentials },
      }),
    }),
  }),
  overrideExisting: false,
});

export const { useRegisterUserMutation } = authApi;
// 新增:导出registerUser endpoint
export const { registerUser } = authApi.endpoints;

修改authSliceNew.js,导入这个导出的endpoint,而非从baseApi获取:

import { createSlice } from "@reduxjs/toolkit";
// 替换导入源,从authApiNew拿registerUser endpoint
import { registerUser } from "./authApiNew";

const initialState = {
  isAuthenticated: false,
  register_success: false,
  feedback: null,
  feedbackType: null,
};

const authSlice = createSlice({
  name: "auth",
  initialState: initialState,
  reducers: {
    resetFeedback: (state) => {
      state.feedback = null;
      state.feedbackType = null;
    },
    resetRegisterSuccess: (state) => {
      state.register_success = false;
    },
  },

  extraReducers: (builder) => {
    builder.addMatcher(
      registerUser.matchFulfilled, // 直接用导出的endpoint
      (state) => {
        state.register_success = true;
        state.feedback = null;
        state.feedbackType = null;
      }
    );
  },
});

export const authActions = authSlice.actions;

export default authSlice;

最后在store/index.js中提前加载authApiNew,确保endpoint注入完成:

import { configureStore } from "@reduxjs/toolkit";
import { setupListeners } from "@reduxjs/toolkit/query";
import { baseApi } from "./baseApi";
// 提前导入authApiNew,保证endpoint先注入到baseApi
import "./authApiNew";
import authSliceNew from "./authSliceNew";

const store = configureStore({
  reducer: {
    [baseApi.reducerPath]: baseApi.reducer,
    authNew: authSliceNew.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(baseApi.middleware),
});

setupListeners(store.dispatch);

export default store;

方法2:用RTK Query内置方法替代extraReducers

如果不需要在auth slice里维护状态,可以直接在mutation中处理逻辑,避免监听endpoint状态:

// authApiNew.js
import { baseApi } from "./baseApi";
import { authActions } from "./authSliceNew";

const authApi = baseApi.injectEndpoints({
  endpoints: (builder) => ({
    registerUser: builder.mutation({
      query: (registerCredentials) => ({
        url: "account/register",
        method: "POST",
        body: { ...registerCredentials },
      }),
      // 使用onQueryStarted触发slice的action
      async onQueryStarted(args, { dispatch, queryFulfilled }) {
        try {
          await queryFulfilled;
          dispatch(authActions.resetFeedback());
          // 这里可以直接dispatch更新auth状态的action
        } catch (error) {
          // 处理注册失败逻辑
        }
      },
    }),
  }),
  overrideExisting: false,
});

export const { useRegisterUserMutation } = authApi;

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 10:12:53