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

RTK Query injectEndpoints执行顺序报错及最佳解决方案咨询

推荐解决方案(按优先级排序)

1. 统一集中注入端点

这是最符合中心化设计原则的方案,完全规避执行顺序问题:
不要将injectEndpoints逻辑分散到各业务文件,将所有端点定义统一收敛到API层,在导出baseApi实例前完成所有端点的注入,保证任何文件导入baseApi时,所有端点都已完成注册。
改造示例:

// api.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import draftableEndpoints from './endpoints/draftables'
// 导入其他所有业务端点定义

const baseApi = createApi({
  reducerPath: "baseApi",
  baseQuery: fetchBaseQuery({
    baseUrl: Globals.BASE_URL + "/api",
    prepareHeaders,
  }),
  endpoints: () => ({}),
});

// 统一注入所有端点
baseApi.injectEndpoints(draftableEndpoints)
// 继续注入其他业务端点

export default baseApi;

对应的端点定义文件调整为导出配置即可:

// endpoints/draftables.js
export default {
  endpoints: build => ({
    getDraftables: build.query({
      query: ({ draftgroupId, gameTypeId }) => "whatever/url",
      transformResponse: ({ data: players }) =>
        players.map(transformApiPlayer),
    }),
  }),
}

2. 用onCacheEntryAdded替代extraReducers匹配

完全解耦切片和API端点的依赖顺序,不需要在切片里匹配请求状态:
在端点定义中添加onCacheEntryAdded钩子,请求成功后直接dispatch切片的同步action更新状态即可。

// draftables.js 端点定义
getDraftables: build.query({
  query: ({ draftgroupId, gameTypeId }) => "whatever/url",
  transformResponse: ({ data: players }) => players.map(transformApiPlayer),
  async onCacheEntryAdded(arg, { dispatch, cacheDataLoaded }) {
    const { data: players } = await cacheDataLoaded
    // 调用currentDraftSlice暴露的setPlayers同步action
    dispatch(setPlayers(players))
  }
})

切片不需要再写extraReducers,正常定义普通reducer即可:

// currentDraftSlice.js
const currentDraftSlice = createSlice({
  name: "currentDraft",
  initialState,
  reducers: {
    setPlayers: (state, action) => {
      state.players = action.payload.map(p => ({
        ...p,
        drafted: false,
      }))
    }
  }
})
export const { setPlayers } = currentDraftSlice.actions

3. 可选兜底方案:加存在性判断

如果要保留现有extraReducers的写法,可以加判断避免访问undefined属性:

extraReducers: builder => {
  // 先判断端点是否已注入,再添加匹配器
  if (baseApi.endpoints.getDraftables) {
    builder.addMatcher(
      baseApi.endpoints.getDraftables.matchFulfilled,
      (state, action) => {
        state.players = action.payload.map(p => ({
          ...p,
          drafted: false,
        }));
      }
    );
  }
}

额外优化建议

如果你的本地players状态不需要跨请求共享修改,也可以直接在查询时通过selectFromResult处理,完全不需要额外的切片存储:

const { data } = useGetDraftablesQuery(params, {
  selectFromResult: ({ data }) => ({
    data: data?.map(p => ({...p, drafted: false}))
  })
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 15:36:06