Skip to content

Gatsby Page Queries — Data Fetching in Page Components

DodaTech Updated 2026-06-28 5 min read

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

  1. Not exporting the query: Page queries must be exported as a named export const query = graphql... Without export, the query isn't processed.
  2. Using non-existent variables: The variable must match what gatsby-node.js passes in context. A mismatch causes a build error.
  3. Querying without checking GraphiQL: Always test queries in GraphiQL first to verify field names and available data.
  4. Forgetting the $ prefix in variables: Query variables use $slug, not slug. The $ distinguishes variables from field names.
  5. Not specifying formatString for dates: Without it, dates are raw strings. Use formatString: "MMMM D, YYYY" for human-readable dates.

Practice Questions

  1. How does a page component receive query results? Answer: Via the data prop. Gatsby injects the query result into the component as data.

  2. What is the role of context in createPage? Answer: It provides variables to the page query. Each key in context becomes a $variable in the GraphQL query.

  3. Can you use aliases in page queries? Answer: Yes. Aliases let you run multiple queries of the same type (e.g., featuredPosts and recentPosts both using allMarkdownRemark).

  4. 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 by createPage.

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

Can I use page queries in layout components?

: No. Page queries only work in page components and template components. Use useStaticQuery in layout components.

Can I use multiple page queries in one component?

: No. Each page component can have only one exported query. Use aliases within the query for multiple datasets.

Are page queries cached?

: Yes. Gatsby caches query results. Changes to source data or query text invalidate the cache.

Can I use fragments in page queries?

: Yes. Define fragments anywhere in your project and reference them in page queries with ...FragmentName.

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