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

RTK Query结合GraphQL与Header Access Token时遇状态序列化错误

问题解决:RTK Query + GraphQL 携带Token请求失败及非序列化错误

问题核心

  1. Postman中可用的Access Token,在RTK Query环境下无法正确携带,请求失败
  2. 每次查询抛出Non-serializable value was detected in the state.错误
  3. 需要实现正常的GraphQL数据获取、错误状态及加载状态管理

错误原因分析

  • graphql-request调用错误:request函数的第三个参数是查询变量,而非请求头,导致Token未正确携带到请求中
  • 不可序列化错误对象:错误处理时直接返回ClientError实例,Redux状态要求所有值必须可序列化,Error实例不符合要求
  • transformResponse处理冗余:错误逻辑应在baseQuery中处理,而非在transformResponse中重复处理

解决方案

1. 修正graphql-request的请求头传递方式

将请求头作为request函数的第四个参数(或放入options对象),确保Token被正确携带

2. 错误处理返回可序列化数据

捕获错误时,仅提取status、message、response data等可序列化属性,避免直接返回Error实例

3. 简化transformResponse逻辑

移除冗余的错误处理,让RTK Query自动管理数据、错误及加载状态

修改后的完整代码

import { createApi } from "@reduxjs/toolkit/query/react";
import { request, gql, ClientError } from "graphql-request";

const API_ENDPOINT = "https://c97663-2.myshopify.com/api/2023-01/graphql.json";

// 符合RTK Query规范的GraphQL基础查询函数
const graphqlBaseQuery =
  ({ baseUrl, headers }: { baseUrl: string; headers: HeadersInit }) =>
  async ({ body }: { body: string }) => {
    try {
      // 正确传递请求头:作为request函数的第四个参数
      const result = await request(baseUrl, body, {}, headers);
      return { data: result };
    } catch (error) {
      if (error instanceof ClientError) {
        const { status, data } = error.response;
        // 返回可序列化的错误对象,不含Error实例
        return {
          error: {
            status,
            message: error.message,
            data: data || {
              message: status === 403 && data?.extensions?.code === "ACCESS_DENIED" 
                ? "Access denied" 
                : "GraphQL request failed"
            }
          }
        };
      }
      // 处理非ClientError类型的错误
      return {
        error: {
          status: 500,
          message: (error as Error).message || "Unknown server error",
          data: {}
        }
      };
    }
  };

export const productsApi = createApi({
  baseQuery: graphqlBaseQuery({
    baseUrl: API_ENDPOINT,
    headers: {
      "X-Shopify-Storefront-Access-Token": "07a059546dee3d048794dc7744f6183a",
      "Content-Type": "application/json",
    },
  }),
  endpoints: (builder) => ({
    getProducts: builder.query({
      query: () => ({
        body: gql`
          query {
            products(first: 10) {
              edges {
                node {
                  id
                  title
                  description
                  productType
                  tags
                  availableForSale
                  createdAt
                  variants(first: 1) {
                    edges {
                      node {
                        id
                        sku
                        title
                        priceV2 {
                          amount
                          currencyCode
                        }
                        image {
                          originalSrc
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        `,
      }),
      // 移除冗余的transformResponse,RTK Query会自动处理数据返回
    }),
  }),
});

export const { useGetProductsQuery } = productsApi;

使用方式

在组件中直接使用生成的Hook,获取数据、错误及加载状态:

import { useGetProductsQuery } from './path/to/productsApi';

const ProductList = () => {
  const { data, error, isLoading } = useGetProductsQuery();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {(error as any).message}</div>;

  return (
    <div>
      {data?.products?.edges.map((edge: any) => (
        <div key={edge.node.id}>
          <h3>{edge.node.title}</h3>
          <p>{edge.node.description}</p>
        </div>
      ))}
    </div>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 08:20:04