Reputation: 1208
Im currently having an issue when using multiple createPage
routes in gatsby-node.js
. I am trying to use Gatsby js with Shopify commerce storefront & and another CMS for blog articles so I need a way of creating routes when viewing products and when viewing blog articles respectively.
Currently, I am experiencing an error that only appears when trying to view a product detail page that reads:
(EnsureResources, ) TypeError: Cannot read property 'page' of undefined
My gatsby-node.js
currently looks like this
const path = require(`path`)
// Create product page urls
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return graphql(`
{
allShopifyProduct {
edges {
node {
handle
}
}
}
}
`).then(result => {
result.data.allShopifyProduct.edges.forEach(({ node }) => {
const id = node.handle
createPage({
path: `/product/${id}/`,
component: path.resolve(`./src/templates/product-page.js`),
context: {
id,
},
})
})
})
}
// Create blog post slug urls
exports.createPages = async ({graphql, actions}) => {
const {createPage} = actions
const blogTemplate = path.resolve('./src/templates/blog.js')
const res = await graphql (`
query {
allContentfulBlogPost {
edges {
node {
slug
}
}
}
}
`)
res.data.allContentfulBlogPost.edges.forEach((edge) => {
createPage ({
component: blogTemplate,
path: `/blog/${edge.node.slug}`,
context: {
slug: edge.node.slug
}
})
})
}
Upvotes: 2
Views: 2338
Reputation: 1569
You can't define the same API (createPages
) twice. Do it in one function, especially since you can all put it into one query.
This code is obviously untested, but should work:
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
{
shopify: allShopifyProduct {
nodes {
handle
}
}
contentful: allContentfulBlogPost {
nodes {
slug
}
}
}
`)
const shopifyTemplate = require.resolve(`./src/templates/product-page.js`)
const contentfulTemplate = require.resolve('./src/templates/blog.js')
if (result.errors) {
return
}
result.data.shopify.nodes.forEach(product => {
const id = product.handle
createPage({
path: `/product/${id}/`,
component: shopifyTemplate,
context: {
id,
},
})
})
result.data.contentful.nodes.forEach(post => {
createPage ({
component: contentfulTemplate,
path: `/blog/${post.slug}`,
context: {
slug: post.slug
}
})
})
}
The nodes
is a shortcut for edges.node
and valid syntax. The shopify:
is an alias before the name of the query. You don't need to use path
, you can also use require.resolve
. The async/await syntax is better to read IMO.
Upvotes: 9