RTK Query对接AppSync请求返回rejected状态问题求助
问题描述
使用RTK Query搭配AppSync(GraphQL)开发React应用时,编写的查询请求在Redux中状态始终为rejected,抛出错误:"Cannot read properties of undefined (reading 'filter')"。
经排查,网络层请求本身执行成功,返回200状态码,问题源于GraphQL客户端适配逻辑。相同请求逻辑下,不使用RTK Query、直接通过Redux Toolkit的createAsyncThunk实现的请求可正常执行,状态为fulfilled,两种实现发出的请求载荷完全一致。
异常代码(RTK Query实现,返回rejected状态)
import { createApi } from '@reduxjs/toolkit/query/react'; import { graphqlRequestBaseQuery } from '@rtk-query/graphql-request-base-query'; import { API } from 'aws-amplify'; import { GRAPHQL_AUTH_MODE } from '@aws-amplify/api-graphql/lib/types'; import { listSurveyTitles } from 'src/graphql/queries'; import aws_exports from 'src/aws-exports'; API.configure(aws_exports); export const surveyTitlesApi = createApi({ reducerPath: 'surveyTitles', baseQuery: graphqlRequestBaseQuery({ url: '/graphql', }), endpoints: (builder) => ({ fetchSurveyTitles: builder.query({ query: ({ limit = 2147483647, params }) => ({ document: API.graphql({ query: listSurveyTitles, variables: { limit, ...params }, authMode: GRAPHQL_AUTH_MODE.API_KEY, }), }), }), }), }); export const { useFetchSurveyTitlesQuery } = surveyTitlesApi;
正常参考代码(Redux Toolkit原生实现,返回fulfilled状态)
export const fetchSurveyTitles = createAsyncThunk( 'planner/fetchSurveyTitles', async ({ limit = 2147483647, ...params }, thunkAPI) => { try { return await API.graphql({ query: listSurveyTitles, variables: { limit, ...params }, authMode: GRAPHQL_AUTH_MODE.API_KEY, }); } catch (e: any) { return thunkAPI.rejectWithValue(e); } } );
问题根因
@rtk-query/graphql-request-base-query是为graphql-request客户端设计的基础查询适配器,内部逻辑要求传入的document字段必须是GraphQL查询字符串或解析后的AST文档,适配器本身会负责发起网络请求。- 异常代码中错误地将
API.graphql()的调用返回值(一个Promise对象)赋值给了document字段,适配器拿到Promise后会尝试按GraphQL文档结构解析、执行字段过滤逻辑,读取不存在的filter属性时直接抛出错误,这个错误发生在参数解析阶段,和网络请求是否成功无关。 - 异常代码本质是混用了两套完全不兼容的GraphQL客户端:Amplify API和graphql-request,逻辑冲突导致报错。
修复方案
弃用不适配Amplify的graphqlRequestBaseQuery,编写适配Amplify GraphQL请求逻辑的自定义baseQuery,和原生createAsyncThunk的请求逻辑保持完全对齐即可,修复后代码如下:
import { createApi } from '@reduxjs/toolkit/query/react'; import { API } from 'aws-amplify'; import { GRAPHQL_AUTH_MODE } from '@aws-amplify/api-graphql/lib/types'; import { listSurveyTitles } from 'src/graphql/queries'; import aws_exports from 'src/aws-exports'; API.configure(aws_exports); // 适配Amplify GraphQL的自定义baseQuery const amplifyGraphqlBaseQuery = () => async ({ query, variables, authMode }) => { try { const result = await API.graphql({ query, variables, authMode: authMode ?? GRAPHQL_AUTH_MODE.API_KEY, }); return { data: result }; } catch (error) { return { error: { status: error?.status || 500, data: error } }; } }; export const surveyTitlesApi = createApi({ reducerPath: 'surveyTitles', baseQuery: amplifyGraphqlBaseQuery(), endpoints: (builder) => ({ fetchSurveyTitles: builder.query({ query: ({ limit = 2147483647, ...params }) => ({ query: listSurveyTitles, variables: { limit, ...params }, }), }), }), }); export const { useFetchSurveyTitlesQuery } = surveyTitlesApi;
内容的提问来源于stack exchange,提问作者Yozz
相关产品推荐
相关产品推荐

