使用Next.js+RTK Query配置queryFn报错,求解决方法
修复Next.js中RTK Query使用queryFn时的报错问题
在Next.js项目中使用RTK Query创建API,采用queryFn而非query配置端点时出现报错,核心问题是RTK Query对queryFn的返回格式有严格要求,而当前代码中ContentApiClient.getNewMovies返回的是Axios原生响应结构,不符合RTK Query的规范。
问题代码
ContentStore.ts
export const contentApi = createApi({ reducerPath: 'api/content', baseQuery: fetchBaseQuery({ baseUrl: '' }), endpoints: (build) => ({ getNewMovies: build.query<any, ContentApi.GetNewMoviesRequestParams>({ queryFn: (params: ContentApi.GetNewMoviesRequestParams) => ContentApiClient.getNewMovies(params), }) }) })
ContentApiClient.ts
class ContentApiClientClass extends ApiClientClass { baseUrl = ContentApiClientConstants.baseUrl async getNewMovies(params?: ContentApi.GetNewMoviesRequestParams) { return await this.getRequest({ url: 'https://jsonplaceholder.typicode.com/posts', params }) } } export const ContentApiClient = new ContentApiClientClass()
ApiClient.class.ts
class ApiClientClass { axiosInstance: AxiosInstance constructor(config?: AxiosRequestConfig) { this.axiosInstance = this.createInstance(config) } private createInstance(config?: AxiosRequestConfig) { return axios.create({ ...config, timeout: 60000, headers: { 'Cache-control': 'no-cache', ...(config?.headers || {}) } }) } private async axiosRequest<R>(context: AxiosRequestConfig): Promise<AxiosResponse<R>> { try { return await this.axiosInstance(context) } catch (error) { if (axios.isCancel(error)) { throw new Error(`Request has aborted. Url: ${context.url}`) } throw error } } async getRequest<R>(context: AxiosRequestConfig): Promise<AxiosResponse<R>> { return await this.axiosRequest({ ...context, method: 'get' }) } } export default ApiClientClass
修复方案
RTK Query要求queryFn必须返回一个包含以下结构的对象:
- 成功时:
{ data: T },其中T是响应数据类型 - 失败时:
{ error: { status?: number, data?: any } },需包含错误状态码和错误数据
修改ContentStore.ts中的queryFn,将Axios响应转换为RTK Query要求的格式:
import { AxiosError } from 'axios'; export const contentApi = createApi({ reducerPath: 'api/content', // 使用queryFn时baseQuery可保留或设为identity(不影响核心逻辑) baseQuery: fetchBaseQuery({ baseUrl: '' }), endpoints: (build) => ({ getNewMovies: build.query<any, ContentApi.GetNewMoviesRequestParams>({ queryFn: async (params) => { try { const response = await ContentApiClient.getNewMovies(params); // 提取Axios响应体,转为RTK Query成功格式 return { data: response.data }; } catch (error) { const axiosError = error as AxiosError; // 提取错误信息,转为RTK Query错误格式 return { error: { status: axiosError.response?.status, data: axiosError.response?.data || axiosError.message } }; } }, }) }) })
额外说明
- 如果不需要
baseQuery,可以将其替换为baseQuery: () => ({})或从@reduxjs/toolkit/query导入identity,因为queryFn会完全接管请求逻辑。 - 建议给响应和错误定义明确的TypeScript类型,替代
any,提升代码类型安全性。
内容的提问来源于stack exchange,提问作者amerance
相关产品推荐
相关产品推荐

