如何在Gatsby的GraphQL请求中避免查询代码重复?
解决方案
Gatsby 原生支持通过 GraphQL 片段(Fragment) 实现查询字段复用,完全替代不可用的字符串插值方案,操作步骤如下:
1. 报错原因说明
Gatsby 的 graphql 标签是在构建阶段静态解析的,不支持运行时字符串插值,因此你之前的写法会触发语法错误。
2. 定义公共复用片段
你可以单独新建一个文件存放全局通用的查询片段(比如 src/graphql/fragments/recetteFields.js),把所有需要复用的字段统一维护在这里:
import { graphql } from 'gatsby' // 单篇食谱的核心字段,所有需要复用的字段都在这里增删 export const recetteCoreFields = graphql` fragment RecetteCoreFields on ContentfulRecette { id nom # 后续新增的字段全部加在这里即可 } ` // 列表查询的外层 edges 结构,直接复用上面的单篇字段 export const allRecetteListStructure = graphql` fragment AllRecetteListStructure on ContentfulRecetteConnection { edges { node { ...RecetteCoreFields } } } `
注:on 后接的类型可以在本地 Gatsby 的 GraphiQL 调试工具(默认地址 http://localhost:8000/___graphql)的文档栏里查询确认,allContentfulRecette 返回的集合类型默认就是 ContentfulRecetteConnection,单篇内容类型为 ContentfulRecette
3. 改写原有查询直接复用片段
你不需要额外处理片段导入的逻辑,只要项目里存在上述片段定义,所有查询都可以直接调用:
无排序无筛选的查询
graphql(` { allContentfulRecette { ...AllRecetteListStructure } } `)
首页带排序的 IndexQuery
graphql` query IndexQuery { posts : allContentfulRecette(sort: {fields: dateDePublication}){ ...AllRecetteListStructure } } `
分类页带筛选的查询
graphql` query allRecettesByCategorie($slug: String!) { recettes : allContentfulRecette( sort: {fields: dateDePublication} filter: {categorie: {elemMatch: {slug: {eq: $slug}}}} ) { ...AllRecetteListStructure } } `
后续你需要修改字段时,仅需要改动最开始定义的 RecetteCoreFields 片段一处,所有引用了该片段的查询会自动同步,完全消除重复维护的成本。
内容的提问来源于stack exchange,提问作者kookoyy
相关产品推荐
相关产品推荐

