loading...

Create individual category pages

notrab profile image Jamie Barton ・2 min read

Since we're linking to /categories/:slug from our list of categories inside CategoryList component, we need to create pages for each of them at build time.

This is where we will hook into a special Gatsby API at build time to do this.

Let's first create the template for our category page. Inside the src directory, create a new folder templates.

Here create a file CategoryPage.js and add the following:

import React from 'react';
import { graphql } from 'gatsby';

import ProductList from '../components/ProductList';

export default function CategoryPage({ data: { category } }) {
  const { products } = category;

  return (
    <React.Fragment>
      <h1>{category.name}</h1>

      <ProductList products={products} />
    </React.Fragment>
  );
}

You'll notice we're not exporting a pageQuery, yet. Let's now export a pageQuery, but this time it will look a little different.

Since this is a "template", it should be used when visiting /categories/:slug.

With Gatsby, we must pass some "context" to the template when building it. This context is available to the GraphQL query as variables, so we can use write a query that uses that variable to fetch the page.

In this case we will use the id of each category nodes to fetch from the Gatsby built Chec nodes.

export const pageQuery = graphql`
  query CategoryPageQuery($id: String!) {
    category: checCategory(id: { eq: $id }) {
      id
      name
      products {
        name
        permalink
        ...PriceInfo
      }
    }
  }
`;

As it stands, this file does nothing itself. So let's put it to action!

Inside the root of your project, create the file gatsby-node.js.

We need to hook into the createPages Gatsby API.

Update gatsby-node.js to include the following:

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  const {
    data: { allChecCategory },
  } = await graphql(`
    {
      allChecCategory {
        nodes {
          id
          slug
        }
      }
    }
  `);

  allChecCategory.nodes.forEach(({ id, slug }) =>
    createPage({
      path: `/categories/${slug}`,
      component: require.resolve(`./src/templates/CategoryPage.js`),
      context: {
        id,
      },
    })
  );
};

Inside the createPages function we're running a GraphQL query to get all of our categories, and for each of those, using the createPage action, and providing it the required path, component, and context.

Discussion

pic
Editor guide