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

如何修改GraphQL返回的数据结构?(Gatsby+Strapi+Apollo场景)

问题描述

背景

站点基于Gatsby构建,搭配提供GraphQL查询的Strapi,以及用于数据获取的Apollo Client。

当前实现

刚在应用中集成Strapi,相关代码如下:
getArticles.ts

import { gql } from "@apollo/client";

export const GET_ARTICLES = gql`
  query Article {
    articles {
      data {
        id
        attributes {
          title
          description
          date
        }
      }
    }
  }
`;

组件中使用:

const { loading, error, data } = useQuery(GET_ARTICLES);

打印data得到的结构:

{
  "data": {
    "articles": {
      "data": [
        {
          "id": "1",
          "attributes": {
            "title": "Article 1",
            "description": "This is the first article",
            "date": "2023-06-23"
          }
        },
        {
          "id": "2",
          "attributes": {
            "title": "Article 2",
            "description": "This is the second article",
            "date": "2023-06-24"
          }
        }
      ]
    }
  }
}

预期效果

期望data直接返回如下数组格式:

[
        {
          "id": "1",
          "attributes": {
            "title": "Article 1",
            "description": "This is the first article",
            "date": "2023-06-23"
          }
        },
        {
          "id": "2",
          "attributes": {
            "title": "Article 2",
            "description": "This is the second article",
            "date": "2023-06-24"
          }
        }
]

疑问

不清楚该修改哪一层实现此效果?虽可在组件中用const myData = data?.articles?.data提取,但不想每次查询都重复写这段代码,希望直接获取目标格式。附gatsby-configs.ts相关配置:

{
      resolve: "gatsby-source-strapi",
      options: {
        apiURL: process.env.STRAPI_API_URL || "http://127.0.0.1:1337",
        accessToken: process.env.STRAPI_TOKEN,
        collectionTypes: [
          {
            singularName: "article",
            queryParams: {
"preview" : "live",
              populate: {
                cover: "*",
                blocks: {
                  populate: "*",
                },
              },
            },
          }
        ]
      },
    },

解决方案

方案1:自定义Apollo useQuery Hook

封装通用Hook自动处理数据提取,避免重复代码:

import { useQuery as useApolloQuery, DocumentNode, QueryHookOptions } from '@apollo/client';

export const useQuery = <T = any>(
  query: DocumentNode,
  options?: QueryHookOptions<T>
) => {
  const { loading, error, data } = useApolloQuery<T>(query, options);
  // 自动提取集合对应的data数组
  const transformedData = data ? Object.values(data)[0]?.data : undefined;
  return { loading, error, data: transformedData };
};

组件中替换原useQuery使用:

import { useQuery } from './path-to-your-custom-hook';
import { GET_ARTICLES } from './getArticles';

const { loading, error, data } = useQuery(GET_ARTICLES);
// 此时data直接是目标数组格式

方案2:Apollo客户端添加响应拦截器

在Apollo Client初始化时添加拦截器,统一处理响应结构:

import { ApolloClient, InMemoryCache, createHttpLink, ApolloLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';

const httpLink = createHttpLink({
  uri: `${process.env.STRAPI_API_URL}/graphql`,
});

// 响应拦截:自动提取集合的data字段
const responseLink = new ApolloLink((operation, forward) => {
  return forward(operation).map((response) => {
    if (response.data) {
      Object.keys(response.data).forEach((key) => {
        if (response.data[key]?.data) {
          response.data[key] = response.data[key].data;
        }
      });
    }
    return response;
  });
});

const authLink = setContext((_, { headers }) => {
  const token = process.env.STRAPI_TOKEN;
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : '',
    },
  };
});

const client = new ApolloClient({
  link: authLink.concat(responseLink.concat(httpLink)),
  cache: new InMemoryCache(),
});

export default client;

之后使用原useQuery时,data.articles直接就是目标数组;若想让返回的data直接为数组,可在拦截器中根据查询名称进一步判断处理。

方案3:使用Gatsby原生GraphQL查询(推荐静态场景)

既然配置了gatsby-source-strapi,直接用Gatsby的静态查询或页面查询,Gatsby会自动将Strapi数据转换为扁平节点结构:

query GetArticles {
  allStrapiArticle {
    nodes {
      id
      title
      description
      date
    }
  }
}

此时data.allStrapiArticle.nodes就是目标数组,且无需手动处理attributes嵌套,更符合Gatsby静态生成的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:43:19