If you’re looking to get started with Gatsby and Contentful have a peek at my Quick Start Guide.
If you’re already a little familiar with Gatsby and Contentful then great, read on!
In this post I’ll be explaining how you can make use of Gatsby’s useStaticQuery hook to query different kinds of data to use around your site.
If you’d prefer to jump ahead you can find this demo site on the links below:
Demo: https://contentfulcontentquerying.gatsbyjs.io/
Repo: https://github.com/PaulieScanlon/contentful-content-querying
Before you get going I’d like to cover off some basics. ☝️
As you may already know there are two main types of GraphQL query that can be used with Gatsby, they are as follows:
-
Page Query
This relates to data that is used by a page or a collection of pages, typically it requires a unique id
so Gatsby can determine what data to return to each page.
It can look a little something like this, but more importantly it can’t be “shared” or reused around your site.
-
useStaticQuery
This method takes advantage of React’s hooks pattern and provides you with a way to query any kind of data. It can look a little something like this and can be “shared” or reused around your site.
Typically speaking you probably wouldn’t use useStaticQuery
to query page content data, but you might, for example, use something like the above which would return a list of the Blog post titles and urls.
useStaticQuery
can be used in a number of ways and in the following examples I’ll show you how to query a list of page links which can be used to create site navigation, and I’ll also explain how to query a list of blog posts links and by using some additional GraphQL functionality you’ll be able to query all the blog posts and the latest blog posts.
Contentful Pages
To help in the creation of navigation you can add some additional fields to your Contentful Page Content Model. This will allow you to filter the data based on some conditions.
Here’s the Content Model for my Contentful Page:
…and here’s the navigation field
navigation
is of type Short Text and by using Contentful’s config options you can add a few extra rules to this field.
You can set the field to be a Required field as well as only allowing specified values. In my demo these are “top-navigation” and “bottom-navigation”.
You can also define a “Default value” for the field. In my demo it’s set to “top-navigation”.
And lastly the field’s “Appearance” can be set to “Dropdown”.
Here’s how that field appears for the Home page in my demo. The field is set as the default value of “top-navigation”.
In the Cookies page however you can see this field is set to “bottom-navigation”.
If you have a look at the demo site again: https://contentfulcontentquerying.gatsbyjs.io/, you’ll see that the Home Page link is at the top of the page in the <header/>
and the Cookies link is at the bottom of the page in the <footer />
.
Creating hooks
To query this data and to help separate the links required in the “top-navigation” and the “bottom-navigation” You can create your own “hook” which contains Gatsby’s useStaticQuery
and then apply a GraphQL filter to test if the navigation field is equal to “top-navigation” or “bottom-navigation”.
To ensure the Home page link, which is “/” appears at position 0 in the list you can sort by the field’s url
.
You can see this hook in the src code here: src/hooks/use-top-navigation.js.
For reference you can see the hook for the bottom navigation below which filters on the value “bottom-navigation” src/hooks/use-bottom-navigation.js.
Using hooks
Since these hooks relate to navigation elements and navigation is typically required to persist across all pages you could add them to Gatsby’s wrapRootElement.
In my demo i’ve created a component called <RootElement />
which i use in both gatsby-browser.js
and gatsby-ssr.js
You can read more about Gatsby’s API’s in the docs:
Import the hook as you normally would and by using Array.prototype.map() you can iterate over the returned values to create a list of links in both the <header />
and the <footer />
.
You can also see how I use these hooks in the src code here: src/componets/root-element.js.
You could also reuse these hooks to create a list of page links for a 404 page for example.
Page Templates
In the demo I’ve used Gatsby’s File System Route API to create a page for each Contentful page… but, and I’m paraphrasing George Orwell here: All pages are equal, but some pages are more equal than others. And just like the pigs some pages may not be the same as others. 🐷
The Home page and the Blog page in the demo site do a little more than just return the data passed from Contentful, they also return a list of blog posts links.
In order to differentiate “/” and “/blog” from the other pages you can add a new field to Contentful’s Page Content Model. In my demo I’ve called this field template
.
template
is of type Short Text and by using Contentful’s config options you can add a few extra rules to this field.
You can set the field to be a Required field as well as only allowing specified values. In my demo these are “home”, “blog” and “default”.
And lastly the field’s “Appearance” is set to “Dropdown”.
Here’s how that field appears for the Blog page in my demo. The field is set to the value of “blog”.
Conditional Pages
Now that pages have a field that makes them different from one another it’s possible to switch the type of template to use when Gatsby builds the page.
You can see this file in the src code here: src/pages/{contentfulPage.url}.js.
Template
Here’s the template I use for the Blog page. There’s a prop named contentfulPage
which is all the data returned by Contentful but you can also import a hook that returns a list of all the blog post links.
You can see the src code for this template here: src/templates/blog-template.js
And the src for the hook can be found here: src/hooks/use-all-blog-posts.js
For the Home page I use a similar technique and use GraphQL to limit the amount of Blog post links returned.
Here’s what that query looks like:
You can see the src code for this template here: src/templates/home-template.js
And the src for the hook can be found here: src/hooks/use-latest-blog-posts.js
And that just about wraps things up. useStaticQuery
is really handy for querying all kinds of data and by abstracting these away into their own hooks means they’re really reusable, they are different to page queries though and I know it can be a little confusing deciding when to use them… my rule of thumb if you like is: if it’s not a page use useStaticQuery
.
I hope you’ve found this helpful and if you have any questions feel free to come find me on Twitter: @PaulieScanlon
Ttfn
Paul 🕺