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

如何在Redux Toolkit的createApi外部使用baseQuery

问题描述

为缩减应用体积,需要移除Redux Toolkit异步thunk中的axios依赖,复用已配置应用全局请求头的baseQuery函数。
原有基于axios的登录thunk实现如下:

export const loginAsyncThunk = createAsyncThunk<loginResponse, loginArgs>(
  'session/login',
  ({ username, password }) => new Promise((resolve, reject) => {
    axios.post(
      ROUTES.LOGIN(),
      { email: username, password }
    )
      .then((response) => resolve(response.data))
      .catch((error: AxiosError | typeof Error) => {
        if (axios.isAxiosError(error)) {
          reject(error.response?.data)
        }
        reject(error)
      })
  })
)

尝试基于fetchBaseQuery改写时,调用baseQuery传入第二、第三个参数为undefined,控制台抛出错误:TypeError: Cannot read property 'signal' of undefined,不清楚baseQuery要求的api、extraOptions参数如何正确配置。
报错时的错误实现:

export const baseQuery = fetchBaseQuery({
  baseUrl: ROUTES.API_HOST,
  prepareHeaders: (headers, api) => {
    // app global headers
    headers.set('Content-Type', `application/json`)
    return headers
  },
})

export const loginAsyncThunk = createAsyncThunk<loginResponse, loginArgs>(
  'session/login',
  ({ username, password }) => new Promise((resolve, reject) => {
    const calledBaseQuery = baseQuery({
      url: ROUTES.LOGIN(),
      body: { email: username, password },
      // @ts-ignore: What should I do with following "api" and "extraOptions"?
    }, undefined, undefined)
    console.log(calledBaseQuery) // Promise {<rejected>: TypeError: Cannot read property 'signal' of undefined}
  })
)
报错原因

fetchBaseQuery返回的baseQuery不是独立可用的通用请求函数,它强依赖上下文参数:

  • 第二个位置的api参数是thunk执行上下文,必须包含signal(请求中断信号)、dispatch、getState等必填属性,传undefined会直接导致内部读取signal属性时报错
  • 第三个位置的extraOptions是自定义扩展配置项,无特殊需求不能传undefined,需传空对象占位
正确实现

createAsyncThunk的payload回调第二个参数会自动注入完整的thunkAPI对象,直接把这个对象传给baseQuery即可,不需要手动构造,也不需要额外包裹Promise层。
修正后的代码:

export const baseQuery = fetchBaseQuery({
  baseUrl: ROUTES.API_HOST,
  prepareHeaders: (headers) => {
    // 保留原有全局请求头配置逻辑
    headers.set('Content-Type', 'application/json')
    return headers
  },
})

export const loginAsyncThunk = createAsyncThunk<loginResponse, loginArgs>(
  'session/login',
  async ({ username, password }, thunkAPI) => {
    const requestResult = await baseQuery(
      {
        url: ROUTES.LOGIN(),
        method: 'POST', // 显式指定POST方法,baseQuery默认发GET请求
        body: { email: username, password },
      },
      thunkAPI, // 直接传入thunk注入的上下文,包含所有baseQuery需要的字段
      {} // 无额外自定义配置时传空对象即可
    )

    // 对齐原有axios版本的错误、成功返回逻辑
    if (requestResult.error) {
      return thunkAPI.rejectWithValue(requestResult.error.data)
    }
    return requestResult.data as loginResponse
  }
)
关键注意点
  • 不要手动构造api参数对象,直接复用createAsyncThunk注入的thunkAPI即可,避免漏传属性导致报错
  • baseQuery默认请求方法为GET,涉及POST/PUT/DELETE等请求必须显式声明method字段
  • 不需要手动套new Promise包装,baseQuery本身返回Promise,直接用async/await写法更简洁,也能避免手写Promise带来的resolve/reject遗漏问题
  • baseQuery返回结果是固定的二元结构:成功时返回{ data: 接口返回值 },失败时返回{ error: 错误对象 },需要手动判断分支处理结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:09:23