Hi folks.
Iām getting done my first job with Gatsby and DatoCMS, and I thought I could go step forward. My client has products, actually few of them. So I created model for him and I used modular content so he could add new products in the future. Like you are probably guessing, Iām trying to map product via graphQL query and display it to the component in Gatsby.
But first things first.
My model looks like that:
And my query:
query SingleProductQuery {
allDatoCmsProduct {
edges {
node {
product {
id
nameOfProduct
descriptionOfProduct
imageOfProduct {
fluid {
...GatsbyDatoCmsFluid_tracedSVG
}
}
}
}
}
}
}
And my component in Gatsby should iterate through each product with that markup:
<StyledProduct>
{
data.allDatoCmsProduct.edges.map(({ node: product }) => (
<div key={product.id}>
<Image fluid={product.imageOfProduct.fluid} />
<ProductName>
<h2>{product.nameOfProduct}</h2>
</ProductName>
<ProductDesc>
<p>{product.descriptionOfProduct}</p>
</ProductDesc>
<ButtonWrapper>
<Button>
<Link to="/">
read <b>mor</b>
</Link>
</Button>
</ButtonWrapper>
</div>
))
}
</StyledProduct>
But I must do something wrong, because itās not working. I tried many configurations but Gatsby is always telling me, that āTypeError: Cannot read property id of undefinedā. I tried to recreate code from Creating a static e-commerce website with Snipcart, GatsbyJS and DatoCMS tutorial, but since the query looks different, I failed. I really hope you can help me guys. Thanks in advance!
hey @leeszczuu looking at your schema, looks like you need to iterate one level deeper. You should iterate again on your product
as that is the modular content inside the product
model. You might want to rename one of the two as I think itās a bit confusing in your case.
But to clarify how the data is structured you should check in your local GraphiQL: http://localhost:8000/___graphql if you try running your query there youāll see that product
itself is an array.
Let me know if I can help you more here.
Thanks Mat for respond. I realized that I missunderstood modular blocks concept and I refcatored my āproductsā into simple model with many fields. Iāve created template file for each product page but I have problems with generating page for each record in Product model.
My gatsby-node files looks like this, which seems fine for me:
const path = require('path')
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions
const template = path.resolve(`src/layouts/product.js`)
return graphql(`
query MyQuerySingleProduct {
allDatoCmsProduct {
edges {
node {
slug
}
}
}
}
`).then(result => {
if (result.errors) {
return Promise.reject(result.errors)
}
result.data.allDatoCmsProduct.edges.forEach(({ node }) => {
console.log(node);
createPage({
path: `/produkt/${node.slug}`,
component: template,
context: {
slug: node.slug
}
})
})
})
}
but I got this error in terminal when run gatsby develop:
ERROR #11321 PLUGIN
"gatsby-source-datocms" threw an error while running the sourceNodes lifecycle:
invalid json response body at https://site-api.datocms.com/site?include=item_types%2Citem_types.fields reason: Unexpected token < in JSON at position 0
FetchError: invalid json response body at https://site-api.datocms.com/site?include=item_types%2Citem_types.fields reason: Unexpec ted token < in JSON at position 0
- body.js:48
[gatsby-classic-theme]/[isomorphic-fetch]/[node-fetch]/lib/body.js:48:31
- next_tick.js:68 process._tickCallback
internal/process/next_tick.js:68:7
Not sure if itās something with Dato or with my code. It would be much appreciate if you could take a look at it
Update:
I added
const { createFilePath } = require(
gatsby-source-filesystem)
at the top of my gatsby-node file and it created pages for each product. Thing is, that all these pages are pulling data from 1 record only. I tried to change datoCmsProduct to allDatoCmsProduct and map it to all nodes but then I get ācannot read property of nullā error highlighting my
<h1{data.allDatoCmsProduct.edges.node.name</h1>
So I reverted this to datoCmsProduct
My product template pages I mentioned above look like this:
import React from 'react';
import { graphql, useStaticQuery } from 'gatsby';
const ProductPage = () => {
const data = useStaticQuery(graphql`
query SingleProductQuery {
datoCmsProduct(id: {eq: "DatoCmsProduct-4695093-en"}) {
name
}
}
`);
return (
<Layout>
<SectionHero>
<h1>{data.datoCmsProduct.name}</h1>
</SectionHero>
</Layout>
)}
export default ProductPage;
My question is how should I construct this ProductPage function to iterate through all nodes within allDatoCmsProduct to make it display all my products content on each page generated?
Thanks in advance!
have a look at our example project on how we fetch content from our pages: https://github.com/datocms/gatsby-portfolio/blob/master/src/templates/work.js
does this help?
I figured it out this morning and this is exactly how I did that Just forgot to mention.
Peace
1 Like