以编程方式生成没有来自 Graphql 的 slug 的 Gatsby 页面
Programatically generating Gatsby pages without a slug from Graphql
我在 WordPress 中设置了一个名为项目的 ACF 选项页面
在“项目”选项页面中,有一个 ACF 转发器允许用户添加多个项目。
在 Gatsby 中,我使用 Graphql 在两个文件中查询我的项目数据:
在自定义挂钩中,允许在我的 Gatsby 站点中全局访问数据
在 gatsby-node.js 文件中,以便为我的模板页面生成一个名为 project-details.js
的 slug
很明显,在 ACF 选项页面的这个转发器字段中,Graphql 中没有 slug。相反,我根据每个项目转发器字段中的嵌套标题文本字段生成一个 slug。
我同时使用 replaceAll() 和 toLowerCase() 方法来创建 slug,然后将其作为我的数据的一部分提供。
这是我的自定义挂钩:
export const useProjectsQueryAlt = () => {
const data = useStaticQuery(graphql`
query ProjectsQueryAlt {
wp {
projects {
projects {
allprojects {
projectContent
projectTitle
featuredImage {
mediaItemUrl
id
}
projectGallery {
caption
id
mediaItemUrl
}
}
}
}
}
}
`)
const project = data.wp.projects.projects.allprojects.map(node => {
const { projectContent, projectTitle, featuredImage, projectGallery } = node;
const title = node.projectTitle;
const spacesToHyphen = title.replaceAll(' ', '-');
const slugFromTitle = spacesToHyphen.toLowerCase()
return {
projectContent,
projectTitle,
slug: slugFromTitle,
featuredImage,
projectGallery: projectGallery.map(node => {
const { caption, id, mediaItemUrl } = node;
return {
caption,
id,
mediaItemUrl
}
})
}
})
return { project }
}
这是我的 gatsby-node 文件:
const path = require('path')
exports.createPages = async ({ graphql, actions }) => {
const { data } = await graphql(`
query Projects {
wp {
projects {
projects {
allprojects {
projectTitle
}
}
}
}
}
`)
data.wp.projects.projects.allprojects.forEach(node => {
const title = node.projectTitle;
const spacesToHyphen = title.replaceAll(' ', '-');
const slugFromTitle = spacesToHyphen.toLowerCase()
actions.createPage({
path: '/projects/' + slugFromTitle,
component: path.resolve('./src/templates/project-details.js'),
context: { slug: slugFromTitle },
})
})
}
这是我的模板文件 project-details.js
import React from 'react'
function ProjectDetails() {
return (
<div>
...my page template content
</div>
)
}
export default ProjectDetails
我现在需要找到一种方法来检查我的“project-details.js”模板文件中的两个附加 slug 是否匹配,以便将相关项目数据显示到相应的 URL。
鉴于我已经在前端生成了 slug,遵循 Gatsby 文档设置动态生成页面与我的用例不一致。我希望有人对这个用例有经验,可以为我指明正确的方向。
您的方法中的问题是您正在根据项目的 title
生成一个“假的”slug,因此您不能使用该字段来过滤任何 GraphQL 节点,因为该字段不存在在项目领域。您最好的选择是使用 title
本身或使用任何自动生成的标识符(id
,如果它作为字段存在)。
actions.createPage({
path: '/projects/' + slugFromTitle,
component: path.resolve('./src/templates/project-details.js'),
context: { title },
})
注:可以省略{ title: title }
您仍然可以使用生成的 slug 的 path
,这是一种有效的方法。
我假设如果 title
是一个唯一字段,那么 slug
也必须是唯一字段,因此您将是一个有效的过滤器。
现在在 project-details.js
:
import React from 'react'
function ProjectDetails({ data }) {
console.log("my data is", data);
return (
<div>
...my page template content
</div>
)
}
export const query = graphql`
query($title: String!) {
yourACFNode(title: { eq: $title} ) {
# your fields
}
}
`
export default ProjectDetails
当然,调整上面的查询以匹配您的 ACF 节点,但得到方法。
我在 WordPress 中设置了一个名为项目的 ACF 选项页面
在“项目”选项页面中,有一个 ACF 转发器允许用户添加多个项目。
在 Gatsby 中,我使用 Graphql 在两个文件中查询我的项目数据:
在自定义挂钩中,允许在我的 Gatsby 站点中全局访问数据
在 gatsby-node.js 文件中,以便为我的模板页面生成一个名为 project-details.js
的 slug
很明显,在 ACF 选项页面的这个转发器字段中,Graphql 中没有 slug。相反,我根据每个项目转发器字段中的嵌套标题文本字段生成一个 slug。
我同时使用 replaceAll() 和 toLowerCase() 方法来创建 slug,然后将其作为我的数据的一部分提供。
这是我的自定义挂钩:
export const useProjectsQueryAlt = () => {
const data = useStaticQuery(graphql`
query ProjectsQueryAlt {
wp {
projects {
projects {
allprojects {
projectContent
projectTitle
featuredImage {
mediaItemUrl
id
}
projectGallery {
caption
id
mediaItemUrl
}
}
}
}
}
}
`)
const project = data.wp.projects.projects.allprojects.map(node => {
const { projectContent, projectTitle, featuredImage, projectGallery } = node;
const title = node.projectTitle;
const spacesToHyphen = title.replaceAll(' ', '-');
const slugFromTitle = spacesToHyphen.toLowerCase()
return {
projectContent,
projectTitle,
slug: slugFromTitle,
featuredImage,
projectGallery: projectGallery.map(node => {
const { caption, id, mediaItemUrl } = node;
return {
caption,
id,
mediaItemUrl
}
})
}
})
return { project }
}
这是我的 gatsby-node 文件:
const path = require('path')
exports.createPages = async ({ graphql, actions }) => {
const { data } = await graphql(`
query Projects {
wp {
projects {
projects {
allprojects {
projectTitle
}
}
}
}
}
`)
data.wp.projects.projects.allprojects.forEach(node => {
const title = node.projectTitle;
const spacesToHyphen = title.replaceAll(' ', '-');
const slugFromTitle = spacesToHyphen.toLowerCase()
actions.createPage({
path: '/projects/' + slugFromTitle,
component: path.resolve('./src/templates/project-details.js'),
context: { slug: slugFromTitle },
})
})
}
这是我的模板文件 project-details.js
import React from 'react'
function ProjectDetails() {
return (
<div>
...my page template content
</div>
)
}
export default ProjectDetails
我现在需要找到一种方法来检查我的“project-details.js”模板文件中的两个附加 slug 是否匹配,以便将相关项目数据显示到相应的 URL。
鉴于我已经在前端生成了 slug,遵循 Gatsby 文档设置动态生成页面与我的用例不一致。我希望有人对这个用例有经验,可以为我指明正确的方向。
您的方法中的问题是您正在根据项目的 title
生成一个“假的”slug,因此您不能使用该字段来过滤任何 GraphQL 节点,因为该字段不存在在项目领域。您最好的选择是使用 title
本身或使用任何自动生成的标识符(id
,如果它作为字段存在)。
actions.createPage({
path: '/projects/' + slugFromTitle,
component: path.resolve('./src/templates/project-details.js'),
context: { title },
})
注:可以省略{ title: title }
您仍然可以使用生成的 slug 的 path
,这是一种有效的方法。
我假设如果 title
是一个唯一字段,那么 slug
也必须是唯一字段,因此您将是一个有效的过滤器。
现在在 project-details.js
:
import React from 'react'
function ProjectDetails({ data }) {
console.log("my data is", data);
return (
<div>
...my page template content
</div>
)
}
export const query = graphql`
query($title: String!) {
yourACFNode(title: { eq: $title} ) {
# your fields
}
}
`
export default ProjectDetails
当然,调整上面的查询以匹配您的 ACF 节点,但得到方法。