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

在Gatsby中如何构建GraphQL数据以包含MDX父目录名称

如何让Gatsby GraphQL返回按类别分组的MDX数据

Gatsby的GraphQL本身无法直接返回带动态类别键的嵌套结构(比如category1、category2这类动态字段),但可以通过提取文件类别信息+查询扁平数据+代码分组的方式实现你要的结构,具体步骤如下:

1. 从文件路径提取类别字段

首先确保gatsby-config.js已配置文件源,指向checks目录:

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `checks`,
        path: `${__dirname}/checks/`,
      },
    },
    `gatsby-plugin-mdx`,
  ],
}

然后在gatsby-node.js中添加onCreateNode钩子,从文件路径里提取类别(即checks下的子目录名),并把这个字段绑定到MDX节点上:

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === `Mdx`) {
    const fileNode = getNode(node.parent)
    // 从相对路径中提取类别:比如checks/category1/example1.mdx,取第1级子目录名
    const category = fileNode.relativeDirectory.split('/')[0]
    createNodeField({
      node,
      name: `category`,
      value: category,
    })
  }
}

2. 查询所有MDX节点数据

在需要使用数据的页面/组件中,编写GraphQL查询获取所有checks目录下的MDX节点,包含我们新增的category字段和frontmatter信息:

query AllChecksQuery {
  allMdx(filter: {fields: {sourceName: {eq: "checks"}}}) {
    nodes {
      fields {
        category
      }
      frontmatter {
        title
        slug
        topic
      }
    }
  }
}

3. 在代码中按类别分组数据

拿到查询结果后,用JavaScript的reduce方法把扁平的节点数组转换成你想要的嵌套结构:

import { graphql } from "gatsby"

export default function ChecksPage({ data }) {
  // 按category分组,生成目标结构
  const groupedChecks = data.allMdx.nodes.reduce((acc, node) => {
    const category = node.fields.category
    if (!acc[category]) {
      acc[category] = { nodes: [] }
    }
    acc[category].nodes.push(node)
    return acc
  }, {})

  // 此时groupedChecks就是你要的结构:{category1: {nodes: [...]}, category2: {...}}
  return (
    <div>
      {Object.entries(groupedChecks).map(([category, { nodes }]) => (
        <section key={category}>
          <h2>{category}</h2>
          <ul>
            {nodes.map((item) => (
              <li key={item.frontmatter.slug}>
                {item.frontmatter.title}
              </li>
            ))}
          </ul>
        </section>
      ))}
    </div>
  )
}

export const query = graphql`
  query AllChecksQuery {
    allMdx(filter: {fields: {sourceName: {eq: "checks"}}}) {
      nodes {
        fields {
          category
        }
        frontmatter {
          title
          slug
          topic
        }
      }
    }
  }
`

为什么GraphQL编辑器无法直接生成该结构?

GraphQL的查询结构是静态定义的,无法返回动态命名的字段(比如动态的category1、category2)。因此必须先获取扁平的节点列表,再在客户端代码中完成分组处理,这是Gatsby这类静态站点生成器的常规实现方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:52:50