Gatsby Page Queries — Data Fetching in Page Components
In this tutorial, you will learn about Gatsby Page Queries. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Gatsby page queries for fetching data in page components with Graphql variables, enabling dynamic page content from files and CMS.
In this lesson, you'll understand how page queries work, how to use variables, and how to query data specific to each page.
What You'll Learn
How to write page queries, use GraphQL variables for dynamic filtering, export queries from page components, and access query results as props.
Why It Matters
Page queries provide data specific to each page. They support variables like slugs and IDs, enabling dynamic page generation from data.
flowchart LR
A[Page Component] --> B[Exported Query]
B --> C[GraphQL Variables]
C --> D[{ slug: $slug }]
D --> E[Query Result]
E --> F[data Prop]
F --> G[Component Renders]
style B fill:#639,color:#fff
style C fill:#4a148c,color:#fff
Basic Page Query
Query data directly in a page component:
import { graphql } from 'gatsby';
import React from 'react';
export default function BlogIndex({ data }) {
return (
<div>
<h1>Blog</h1>
{data.allMarkdownRemark.nodes.map(post => (
<article key={post.id}>
<h2>{post.frontmatter.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
);
}
export const query = graphql`
query BlogListQuery {
allMarkdownRemark(sort: { frontmatter: { date: DESC } }) {
nodes {
id
frontmatter { title date(formatString: "MMMM D, YYYY") }
excerpt(pruneLength: 200)
fields { slug }
}
}
}
`;
Output: The page receives a data prop containing all blog posts. Query results are automatically passed to the default exported component.
Page Query with Variables
Use variables for dynamic pages:
import { graphql } from 'gatsby';
import React from 'react';
export default function BlogPost({ data }) {
const post = data.markdownRemark;
return (
<article>
<h1>{post.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</article>
);
}
export const query = graphql`
query BlogPostBySlug($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
title
date(formatString: "MMMM D, YYYY")
tags
}
}
}
`;
Output: The $slug variable is passed from gatsby-<a href="/backend/nodejs/">Node.js</a> when creating pages with createPage. Each post gets its content via the variable.
Providing Variables from gatsby-node.js
Connect page queries with programmatic page creation:
// gatsby-node.js
const path = require('path');
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const result = await graphql(`
query {
allMarkdownRemark {
nodes {
fields { slug }
}
}
}
`);
result.data.allMarkdownRemark.nodes.forEach(node => {
createPage({
path: node.fields.slug,
component: path.resolve('./src/templates/blog-post.js'),
context: {
slug: node.fields.slug // Passed as $slug to the page query
}
});
});
};
Output: For each Markdown file, Gatsby creates a page with the post's slug. The context object passes slug as the $slug variable to the page query.
Multiple Queries with Aliases
Fetch different data in one page query:
export const query = graphql`
query HomePage($category: String) {
featuredPosts: allMarkdownRemark(
filter: { frontmatter: { featured: { eq: true } } }
limit: 3
) {
nodes { frontmatter { title } excerpt }
}
recentPosts: allMarkdownRemark(
sort: { frontmatter: { date: DESC } }
limit: 10
) {
nodes { frontmatter { title date } }
}
}
`;
Output: The component receives data.featuredPosts and data.recentPosts as separate arrays. Aliases let you run multiple queries of the same type.
Querying Images in Page Queries
export const query = graphql`
query ProductPage($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
frontmatter {
title
heroImage {
childImageSharp {
gatsbyImageData(
width: 1200
placeholder: BLURRED
formats: [AVIF, WEBP, AUTO]
)
}
}
}
}
}
`;
Output: The hero image associated with the product page is optimized by gatsby-plugin-image. The component uses getImage() and GatsbyImage to render it.
Common Mistakes
- Not exporting the query: Page queries must be exported as a named
export const query = graphql... Without export, the query isn't processed. - Using non-existent variables: The variable must match what
gatsby-node.jspasses incontext. A mismatch causes a build error. - Querying without checking GraphiQL: Always test queries in GraphiQL first to verify field names and available data.
- Forgetting the
$prefix in variables: Query variables use$slug, notslug. The$distinguishes variables from field names. - Not specifying
formatStringfor dates: Without it, dates are raw strings. UseformatString: "MMMM D, YYYY"for human-readable dates.
Practice Questions
How does a page component receive query results? Answer: Via the
dataprop. Gatsby injects the query result into the component asdata.What is the role of
contextincreatePage? Answer: It provides variables to the page query. Each key incontextbecomes a$variablein the GraphQL query.Can you use aliases in page queries? Answer: Yes. Aliases let you run multiple queries of the same type (e.g.,
featuredPostsandrecentPostsboth usingallMarkdownRemark).What happens if you export a query from a non-page component? Answer: Nothing. Page queries only work in files under
src/pages/or in template components used bycreatePage.
Challenge
Create a tag archive page that uses a page query with a $tag variable. The page should list all posts with that tag, and gatsby-node.js should create one page per tag.
Mini Project
Build a paginated blog listing. Create 20+ blog posts, implement pagination using skip and limit in page queries, and generate navigable page numbers.
FAQ
What's Next
Learn about Gatsby Source Plugins to understand how to pull data from filesystems, CMS platforms, and APIs.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro