Fragments

How to use fragments to make your queries modular in your Gatsby project with Prismic.


What are fragments?

Fragments are a way of splitting your GraphQL queries. They allow you to break down large queries into smaller ones, making them reusable and unique to a component's code. Page queries become more clear and Slice components more modular. Everything that belongs to the Slice is in the same component file.

In Prismic Slice components and the Slice Zone are great examples of usage for Fragments.

For example, look at this page query that uses fragments. Both queries work in the same way, only that fragments make the code shorter and more intelligible.

  • With fragments
  • Without fragments
Copy
query pageQuery($id: String, $lang: String) {
  prismicPage(id: {eq: $id}, lang: {eq: $lang}) {
    data {
      body {
        ... on PrismicSliceType {
          id
          slice_label
          slice_type
        }
        ...PageDataBodyEmailSignup
        ...PageDataBodyFullWidthImage
        ...PageDataBodyHeadlineWithButton
        ...PageDataBodyInfoWithImage
        ...PageDataBodyTextInfo
      }
    }
  }
}
Copy
query pageQuery($id: String, $lang: String) {
  prismicPage(id: {eq: $id}, lang: {eq: $lang}) {
    data {
      body {
        ... on PrismicSliceType {
          id
          slice_label
          slice_type
        }
        ... on PrismicPageDataBodyEmailSignup {
          id
          primary {
            section_title {
              raw
            }
          }
          slice_type
        }
        ... on PrismicPageDataBodyFullWidthImage {
          id
          primary {
            image {
              alt
              url
            }
          }
          slice_type
        }
        ... on PrismicPageDataBodyHeadlineWithButton {
          id
          primary {
            description {
              raw
            }
          }
          slice_type
        }
        ... on PrismicPageDataBodyInfoWithImage {
          id
          primary {
            text {
              raw
            }
          }
          slice_label
        }
        ... on PrismicPageDataBodyTextInfo {
          id
          primary {
            section_title {
              raw
            }
          }
          slice_type
        }
      }
    }
  }
}

When you add a fragment to a component and then import that component to a page, Gatsby and GraphQL automatically know that the fragment can be used in a page query.

Now let's see a couple of use cases to understand better how fragments work.

Single Slice example

In this example, we query a document of the type "Home". It has a Slice with the API ID of Text.

Page query

We write the full query in the homepage template. In this case, it's an index.js file. Then we import and render the Text component. See how the query changes when we replace the Slice with a fragment called TextSlice.

  • With fragments
  • Without fragments
Copy
// Example 〜/src/pages/index.js file

import * as React from 'react'
import { graphql } from 'gatsby'
import { Text } from '../components/text'

const Home = ({ data }) => {
  if (!data) return null

  const pageContent = data.prismicHome
  const page = pageContent.data || {}

  return (
    <div>
      <Text slice={page.body} />
    </div>
  )
}

export const query = graphql`
  query HomeQuery {
    prismicHome {
      data {
        body {
          ...TextSlice
        }
      }
    }
  }
`

export default Home
Copy
// Example 〜/src/pages/index.js file

import * as React from 'react'
import { graphql } from 'gatsby'
import { Text } from '../components/text'

const Home = ({ data }) => {
  if (!data) return null

  const pageContent = data.prismicHome
  const page = pageContent.data || {}

  return (
    <div>
      <Text slice={page.body} />
    </div>
  )
}

export const query = graphql`
  query HomeQuery {
    prismicHome {
      data {
        body {
          ... on PrismicHomeDataBodyText {
            id
            primary {
              content {
                raw
              }
            }
          }
        }
      }
    }
  }
`

export default Home

Text Slice component

Now, we'll use the Slice query to build the TextSlice fragment inside the Text component.

  • With fragments
  • Without fragments
Copy
// Example 〜/src/components/Text.js file

import * as React from 'react'
import { graphql } from 'gatsby'
import { RichText } from 'prismic-reactjs'

export const Text = ({ slice }) => (
  <section className="text">
    <RichText render={slice[0].primary.right_column_text.raw} />
  </section>
)

export const query = graphql`
  fragment TextSlice on PrismicHomeDataBodyText {
    id
    primary {
      content {
        raw
      }
    }
  }
`
Copy
// Example 〜/src/components/Text.js file

import * as React from 'react'
import { RichText } from 'prismic-reactjs'

export const Text = ({ slice }) => (
  <section className="text">
    <RichText render={slice[0].primary.right_column_text.raw} />
  </section>
)

When you import the component to the index.js file, it will automatically recognize the fragment and add it to the page query.

Shared Slices example

You'll usually reuse your Slices between many of your Custom Types. You can modify your fragments within the components to be suitable for any Custom Type query.

For example, let's say that you have two Custom Types: article and post, and you use an Image Gallery Slice in both. You can add the fragment corresponding to each type within the ImageGallery.js component query, with a unique name for each one.

Once done, you can call your Slice/Component from both the post and article queries in the query body, like so: ...PostImageGallery and ...ArticleImageGallery.

  • Image Gallery component
  • Post template
  • Article template
Copy
// Example 〜/src/components/ImageGallery.js file

import * as React from 'react'
import { graphql } from 'gatsby'
import { RichText } from 'prismic-reactjs'

export const ImageGallery = ({ slice }) => {
  return (
    <section className="image-gallery content-section">
      <RichText render={slice[0].primary.carousel_title.raw} />
      <div className="gallery">
        {slice[0].items.map((galleryItem, index) => (
          <div className="gallery-item" key={`gallery-item=${index}`}>
            <img src={galleryItem.image.url} alt={galleryItem.image.alt} />
            <RichText render={galleryItem.image_description.raw} />
          </div>
        ))}
      </div>
    </section>
  )
}


export const query = graphql`
  fragment PostImageGallerySlice on PrismicPostDataBodyImageGallery {
    slice_type
    primary {
      carousel_title {
        raw
      }
    }
    items {
      image {
        url
        alt
      }
      image_description {
        raw
      }
    }
  }
  fragment ArticleImageGallerySlice on PrismicArticleDataBodyImageGallery {
    slice_type
    primary {
      carousel_title {
        raw
      }
    }
    items {
      image {
        url
        alt
      }
      image_description {
        raw
      }
    }
  }
`
Copy
// Example 〜/src/pages/Post.js file

import * as React from 'react'
import { graphql } from 'gatsby'
import { ImageGallery } from '../components/ImageGallery'

const Post = ({ data }) => {
  if (!data) return null

  const postContent = data.prismicPost
  const post = postContent.data || {}

  return (
    <div>
      <ImageGallery slice={post.body} />
    </div>
  )
}

export const query = graphql`
  query PostQuery {
    prismicPost {
      data {
        body {
          ...PostImageGallerySlice
        }
      }
    }
  }
`

export default Post
Copy
// Example 〜/src/pages/Article.js file

import * as React from 'react'
import { graphql } from 'gatsby'
import { ImageGallery } from '../components/ImageGallery'

const Article = ({ data }) => {
  if (!data) return null

  const articleContent = data.prismicArticle
  const article = articleContent.data || {}

  return (
    <div>
      <ImageGallery slice={article.body} />
    </div>
  )
}

export const query = graphql`
  query ArticleQuery {
    prismicArticle {
      data {
        body {
          ...ArticleImageGallerySlice
        }
      }
    }
  }
`

export default Article

When you import the ImageGallery.js component to the Page.js and Article.js files, Gatsby and GraphQL will automatically recognize the fragment and add it to the page query.

More resources

If you want to learn more about fragments, here are some more resources for you to explore:


Was this article helpful?
Not really
Yes, Thanks

Can't find what you're looking for? Get in touch with us on our Community Forum.