基于许多内容引用使用 Gatsby 动态创建页面
Posted
技术标签:
【中文标题】基于许多内容引用使用 Gatsby 动态创建页面【英文标题】:Dynamically create pages with Gatsby based on many Contentful references 【发布时间】:2021-07-02 02:55:17 【问题描述】:我目前正在使用 Gatsby 的 collection routes API 为一个简单的博客创建页面,其中的数据来自 Contentful。
例如,为每个博文类别创建一个页面:
-- src/pages/categories/contentfulBlogPost.category.js
export const query = graphql`
query categoriesQuery($category: String = "")
allContentfulBlogPost(filter: category: eq: $category )
edges
node
title
category
description
description
...
...
[React component mapping all blogposts from each category in a list]
...
这工作正常。
但现在我希望每个博文有多个类别,所以我切换到 Contentful 的 references, many
内容类型,它允许一个字段有多个条目:
现在我对字段 category2
的 graphQL 查询的结果是每个博文的不同类别的数组:
查询:
query categoriesQuery
allContentfulBlogPost
edges
node
category2
id
name
slug
输出:
"data":
"allContentfulBlogPost":
"edges": [
"node":
"category2": [
"id": "75b89e48-a8c9-54fd-9742-cdf70c416b0e",
"name": "Test",
"slug": "test"
,
"id": "568r9e48-t1i8-sx4t8-9742-cdf70c4ed789vtu",
"name": "Test2",
"slug": "test-2"
]
,
"node":
"category2": [
"id": "75b89e48-a8c9-54fd-9742-cdf70c416b0e",
"name": "Test",
"slug": "test"
]
,
...
现在类别在数组中,我不知道如何:
编写一个查询变量来过滤类别名称; 使用 slug 字段作为路由来动态创建页面。对于我正在做的博文作者:
query authorsQuery($author__slug: String = "")
allContentfulBlogPost(filter: author: slug: eq: $author__slug )
edges
node
id
author
slug
name
...
...
并使用src/pages/authors/contentfulBlogPost.author__slug.js
创建页面
我想我必须改用 createPages API。
【问题讨论】:
【参考方案1】:您可以使用 Filesystem API 实现结果,类似这样的方法可能有效:
src/pages/category/contentfulBlogPost.category2__name.js
在这种情况下,这种方法似乎会导致一些警告,因为您可能会创建具有相同 URL (slug
) 的重复页面,因为帖子可能包含多个重复的类别。
但是,我认为使用您所说的createPages
API 更简洁,请记住,您需要处理类别以避免重复,因为它们是一对多 em> 关系。
exports.createPages = async ( graphql, actions ) =>
const createPage = actions
const result = await graphql(`
query
allContentfulBlogPost
edges
node
category2
id
name
slug
`)
let categories= slugs: [], names: [] ;
result.data.allContentfulBlogPost.edges.map((node))=>
let name, slug = node.category2;
// make some checks if needed here
categories.slugs.push(slug);
categories.names.push(name);
return new Set(categories.slugs) && new Set(categories.names);
);
categories.slugs.forEach((category, index) =>
let name = categories.names[index];
createPage(
path: `category/$category`,
component: path.resolve(`./src/templates/your-category-template.js`),
context:
name
);
);
代码非常不言自明。基本上,您正在定义一个空对象 (categories
),其中包含两个数组 slugs
和 names
:
let categories= slugs: [], names: [] ;
之后,您只需遍历查询结果(result
)并将字段值(name
、slug
和其他如果需要)推送到前一个数组,进行所需的检查如果您愿意(避免推送空值或匹配某些正则表达式等)并返回 new Set
以删除重复项。
然后,您只需要循环使用createPage
API 创建页面并通过上下文传递所需的数据:
context:
name
由于冗余,这和做的一样:
context:
name: name
因此,在您的模板中,您将获得pageContext
props
中的名称。如果需要,将其替换为 slug
,具体取决于您的情况和用例,方法完全相同。
【讨论】:
感谢您的详细解答!以上是关于基于许多内容引用使用 Gatsby 动态创建页面的主要内容,如果未能解决你的问题,请参考以下文章
如何选择性地查询 gatsby Contentful Rich Text 中的引用?