Reputation: 109
I've added a blog page that I integrated with NetlifyCMS and it works wonderful. However, I need to have one more dynamic page on my site that displays services and each service will have its own generated template, will pretty much be very similar to the blog page in theory.
So I read around a bunch of different solutions but kept hitting a wall. What am I doing wrong here? and whats the simplest way to make this work, as I wont be adding any other dynamic pages moving forward.
Here was my gatsby-node.js when I just had the blog page and everything worked great:
const { createFilePath } = require("gatsby-source-filesystem")
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
//Blog
async function getPageData(graphql) {
return await graphql(`
{
blogPosts: allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
}
const path = require(`path`)
exports.createPages = async ({ graphql, actions }) => {
const { data } = await getPageData(graphql)
data.blogPosts.edges.forEach(({ node }) => {
const { slug } = node.fields
actions.createPage({
path: `/articles${slug}`,
component: path.resolve("./src/templates/articlepost.js"),
context: {slug: slug },
})
})
}
So I took a stab it and tried to do the same thing but adding my services page. Here is what that ended up looking like:
gatsby-node.js
const { createFilePath } = require("gatsby-source-filesystem")
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
async function getBlogData(graphql) {
return await graphql(`
{
blogPosts: allMarkdownRemark(
filter: { frontmatter: { template: { eq: "articlepost" } } }
) {
edges {
node {
fields {
slug
}
}
}
}
}
`)
}
async function getServiceData(graphql) {
return await graphql(`
{
servicePosts: allMarkdownRemark(
filter: { frontmatter: { template: { eq: "service" } } }
) {
edges {
node {
fields {
slug
}
}
}
}
}
`)
}
const path = require(`path`)
exports.createPages = async ({ graphql, actions }) => {
const blogPage = path.resolve("./src/templates/articlepost.js")
const servicePage = path.resolve("./src/templates/service.js")
const { data } = await getBlogData(graphql)
data.blogPosts.edges.forEach(({ node }) => {
const { slug } = node.fields
actions.createPage({
path: `/articles${slug}`,
component: blogPage,
context: { slug: slug },
})
})
const { serviceData } = await getServiceData(graphql)
serviceData.servicePosts.edges.forEach(({ node }) => {
const { slug } = node.fields
actions.createPage({
path: `/streaming-services${slug}`,
component: servicePage,
context: { slug: slug },
})
})
}
My blog page still works fine but I get error:
As you can see I added a template type to my config.yml, that now shows in my frontmatter to separate my posts, but I think it may have just confused me a little more. Totally fine with removing the template types from frontmatter, but really need a very simple way for this to work.
Many thanks in advance!
Upvotes: 1
Views: 57
Reputation: 8418
const { serviceData } = await getServiceData(graphql)
doesn't work as no serviceData
in object returned from graphql(
(returned by getServiceData
) - it's always a data
named property.
You can reuse data
(if earlier data
not required later) or use alias in destructuring:
const { data: serviceData } = await getServiceData(graphql)
Upvotes: 0
Reputation: 29315
Try aliasing your loops to avoid scoped elements.
const { data } = await getBlogData(graphql)
data.blogPosts.edges.forEach(({ node: post }) => {
const { slug } = post.fields
actions.createPage({
path: `/articles${slug}`,
component: blogPage,
context: { slug: slug },
})
})
And:
serviceData.servicePosts.edges.forEach(({ node: service }) => {
const { slug } = service.fields
actions.createPage({
path: `/streaming-services${slug}`,
component: servicePage,
context: { slug: slug },
})
})
Basically, you are aliasing the loop item to make them unique (different from the previous loop) as post
and service
respectively.
I would recommend reading this article from David Walsh.
Upvotes: 1