Gatsby: Why Do I (Or Do I Even?) Need to Use exports.onCreateNode to Create Pages?

Viewed 257

All of the examples in the Gatsby documentation seem to assume you want to define an exports.onCreateNode first to parse your data, and then define a separate exports.createPages to do your routing.

However, that seems needlessly complex. A much simpler option would seem to be to just use the graphql option provided to createPages:

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;
  const { data } = await graphql(query);
  // use data to build page
  data.someArray.forEach(datum => 
    createPage({ path: `/some/path/${datum.foo}`, component: SomeComponent }));

However, when I do that, I get an error:

TypeError: filepath.includes is not a function

I assume this is because my path prop for createPage is a string and it should be "slug". However, all the approaches for generating slugs seem to involve doing that whole exports.onCreateNode thing.

Am I missing a simple solution for generating valid slugs from a path string? Or am I misunderstanding Gatsby, and for some reason I need to use onCreateNode every time I use createPage?

2 Answers

It turns out the error I mentioned:

TypeError: filepath.includes is not a function

Wasn't coming from the path prop at all: it was coming from the (terribly named) component prop ... which does not take a component function/class! Instead it takes a path to a component (why they don't call the prop componentPath is just beyond me!)

But all that aside, once I fixed "component" to (sigh) no longer be a component, I was able to get past that error and create pages ... and it turns out the whole onCreateNode thing is unnecessary.

Why Do I Need to Use exports.onCreateNode to Create Pages?

You do not.

Gatsby heavily uses GraphQL behind the scenes. The Gatsby documentation is about teaching users that many of the features in Gatsby are often only available via GraphQL.

You can create pages without GraphQL as you do in answer with data.someArray.forEach ... but that is not the intended way. By skipping createNodeField you will not be able to query for these fields within your page queries. If you don't need these fields via GraphQL then your solution is perfect.

Related