I’m trying to create dynamic product page in Gatsby.
Here is what I’ve edited in file gatsby-node.js
exports.createPages = async ({ graphql, actions }) => {
const { createRedirect } = actions
const { createPage } = actions
const {
data: { products },
} = await graphql(`
{
products: allTestJson {
edges {
node {
brand
category
}
}
}
}
`)
const nodeArray = products.edges.map(edge => edge.node.brand)
const unique = [...new Set(nodeArray)]
console.log("UNIQUE")
console.log(unique)
unique.forEach((brand) => {
console.log("BRAND")
console.log(brand)
createPage({
path: `/products/${brand}`,
component: require.resolve(`./src/pages/contact-us.js`),
})
})
}
Here I do the console.log and I’m sure the ${node.brand}
returns a value. (One of it is "faro"). However, when I visit /products/faro on the browser, I only see a big white blank page:
When I change the path to path: "path: /products/faro
" (just hard code path as products/faro), then the page component renders correctly.
Is there something wrong with the loop or variable? I’m following this tutorial https://dev.to/notrab/build-static-product-pages-with-gatsby-and-commerce-js-3952
import React, { Component } from "react"
import styled from "styled-components"
import { injectIntl, Link, FormattedMessage } from "gatsby-plugin-intl"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { Background } from "../components/layout/Background"
import { Space } from "../components/layout/Space"
import ShowroomGrid from "../components/organisms/ShowroomGrid"
import ContactForm from "../components/organisms/ContactForm"
import Map from "../components/molecules/Map"
class ContactUs extends Component {
state = {
responsiveSize: null,
}
componentDidMount = () => {
this.setState({
responsiveSize: window.innerWidth,
})
}
render() {
const { responsiveSize } = this.state
return (
<Layout>
<SEO
description="Visit our showrooms in Ho Chi Minh City & Hanoi to admire the timeless masterpieces from Fritz Hansen, Flos, Louis Poulsen, Fontana Arte & Faro."
title="Contact Us - nanoHome showrooms in HCM & Hanoi"
keywords={[`luxury`, `lighting`, `furniture`, `showroom`]}
/>
<Background>
<MainContainer className="main-container">
<Space height="64" />
<H1Tag>nanoHome | Contact Us</H1Tag>
<SectionMapAndContact responsiveSize={responsiveSize}>
<GoogleMap>
<Map />
</GoogleMap>
<Contacts>
<Title>
<FormattedMessage id="page-contact-us.section-map-and-contact.title" />
</Title>
<Space height="48" />
<Address>
<b>
<FormattedMessage id="page-contact-us.section-map-and-contact.office" /> </b> <Space height="16" />
<p>
<FormattedMessage id="page-contact-us.section-map-and-contact.address" />
</p>
<Space height="16" />
<p>+84 90 984 0028</p>
<Space height="8" />
<p>[email protected]</p>
<Space height="8" />
<p>www.nanohome.vn</p>
</Address>
</Contacts>
</SectionMapAndContact>
<Space height="64" />
<SectionShowrooms>
<Title>Our Showrooms</Title>
<Space height="48" />
<ShowroomGrid responsiveSize={responsiveSize} />
</SectionShowrooms>
<Space height="64" />
<SectionContactForm responsiveSize={responsiveSize}>
<Title>Get in Touch</Title>
<Space height="48" />
<ContactForm />
</SectionContactForm>
</MainContainer>
</Background>
</Layout>
)
}
}
const MainContainer = styled.div`
margin: 0 auto;
`
const SectionMapAndContact = styled.div`
max-width: 960px;
margin: auto;
padding: 0 2rem;
display: grid;
grid-template-columns: ${props =>
props.responsiveSize > 1024 ? "1fr 1fr" : "1fr"};
grid-template-rows: ${props =>
props.responsiveSize < 1024 ? "1fr auto" : "1fr"};
align-items: center;
justify-content: center;
grid-gap: ${props => (props.responsiveSize > 1024 ? "4rem" : "2rem")};
`
const GoogleMap = styled.div`
width: 100%;
height: 500px;
`
const Contacts = styled.div`
width: 100%;
max-width: 440px;
`
const Title = styled.h2`
font-size: var(--font-size-larger);
color: var(--color-primary-blue);
font-family: "Miller";
`
const Address = styled.div`
color: var(--color-primary-blue);
font-size: var(--font-size-large);
border-left: 2px solid var(--color-primary-blue);
padding: 0 2rem;
p {
font-size: var(--font-size-medium);
line-height: 1.5;
margin: 0;
}
`
const SectionShowrooms = styled.div`
padding: 0 2rem;
max-width: 960px;
margin: auto;
`
const SectionContactForm = styled.div`
width: ${props =>
(props.responsiveSize > 1024 && "24%") ||
(props.responsiveSize > 768 && "50%") ||
(props.responsiveSize > 480 && "80%") ||
"100%"};
margin: auto;
max-width: 960px;
padding: 0 2rem;
min-width: 320px;
display: flex;
flex-direction: column;
align-items: center;
`
const H1Tag = styled.h1`
visibility: hidden;
font-size: var(--font-size-smaller);
`
export default ContactUs
I also add the debug of unique Array and brand here (sorry it’s quite messy as I’m outside)
2
Answers
The problem is the "brand data" that I loaded from graphql has some capital letters, and the browser always lowercase text, so it does not match the path in gatsby-node.js. Thank you @harley for spotting this. Thank you for all your help.
The fact that you’re not getting a 404 page indicates that your page is being created correctly.
Is it possible the page is expecting some sort of props? In the tutorial you linked, it looks like they are passing an
id
prop. To pass such props you need to pass acontext
arg tocreatePage
(eg.createPage({ component, path, context: { id })
) … but the code you provided doesn’t have any.Whatever the problem is, it seems likely that it’s in
contact-us.js
, so you’ll need to debug it.