How GraphQL Query Passes its Response Back to Gatsby React Components
Andre Roussakoff
Madrus4UTL;DR When I started learning Gatsby, I wanted to understand the magic of GraphQL queries passing their results back to the React component. My secondary focus was to use React functional components instead of React class components as much as possible. In this blogpost, I have summarized my findings.
Most of the information comes from Gatsby Documentation and from my personal test projects.
#
Page QuerySuppose we have our site metadata defined in gatsby-config.js
:
Then in the src/pages/HomePage.js
(or index.js
) we can write the following code, which will show the description The most wonderful description of my website goes here.
on the page:
So, where does the HomePage
function get its data
from? Here we have the famous "Convention over Configuration" principle at work:
- the
site
field in the GraphQL query refers to thegatsby-config.js
file above; thesiteMetadata
object with thedescription
field gets exported there; - the GraphQL query itself is (and should be!) also exported:
export const query = graphql
; - as a result, the query response is passed as the
data
prop to theHomePage
function and can be destructured as{ data }
from its props.
#
Page Query with Query VariablesWith page queries we can go a step further and add query variables to the GraphQL query. The following example shows how it can be done. It is extra interesting because it is also an example of how to query the .mdx
pages in our project.
Let us look at this query in the src/templates/blog-post.js
file:
It uses $title
as a variable and searches the MDX-nodes in the project site with the title
that equals the $title
string value.
For this to work,
the
MdxBlogPost
query should havegatsby-plugin-mdx
plugin installed, andserving of the
.mdx
files should be configured viagatsby-source-filesystem
plugin in thegatsby-config.js
file.
When a page is created dynamically from the blog post template in gatsby-node.js
, you can provide an object as part of the page’s context. Keys in the context object that match up with arguments in the page query (in this case: "title"
), will be used as variables. Variables are prefaced with $
, so passing a title
property will become$title
in the query.
#
StaticQueryGatsby v2 introduced StaticQuery
, a new API that allowed not only pages but any component to retrieve data via a GraphQL query.
The table below shows the differences between page queries and the StaticQuery element.
Page Query | StaticQuery |
---|---|
works only in Pages | works in any React component including Pages |
accepts variables via pageContext | accepts no variables |
works with React.createElement | does not work with React.createElement , instead it is itself a JSX <StaticQuery /> element |
default export: the page query itself | default export: an anonymous function, which returns the StaticQuery element |
Simply said the StaticQuery
is a JSX-element with 2 parameters:
query
that holds a query definition, andrender
that holds a function returning a JSX-element
It handles the query result in a different way than a page query. Let us consider the following code snippet:
How it works is that the result of the query in the query
parameter automagically becomes the value of the render
function data
argument.
Notice the
export default () => (...)
signature similar to that of the page query except that here we have an anonymous default export.
#
From StaticQuery to useStaticQuery hookReact hooks are becoming more and more popular, and Gatsby has created its own: useStaticQuery hook. It is based on the StaticQuery
element and requires at least version 16.8.0 of React
and ReactDOM
packages. Let us rewrite the previous example using this hook:
Here, we extract data
object from the useStaticQuery
hook and then use it in the JSX-element we return from the default anonymous export.
#
Known Limitations of useStatic QueryAs Gatsby documentation states, useStaticQuery
- does not accept variables (hence the name “static”), but can be used in any component, including pages;
- because of how queries currently work in Gatsby, only a single instance of
useStaticQuery
per file is supported.
#
Closing WordsWe have considered three options how to use GraphQL in Gatsby:
- Page Queries to use only on pages
- StaticQuery to use in any JSX-component
- useStaticQuery hook to use in any JSX-component
For every option we have shown how the query result is passed to the corresponding presentational component.