Rendering the Slice Zone

Prismic no longer recommends the gatsby-source-prismic-graphql plugin

With recent changes to Gatsby, Prismic no longer recommends the gatsby-source-prismic-graphql plugin that this documentation uses. Read more about the future of Prismic and Gatsby. We highly recommend using the gatsby-source-prismic instead. The documentation for this plugin can be found in the plugin's github README.

We will leave this documentation here for now, but will change it in the future when we determine the best approach for Prismic & Gatsby.

The Slices field is used to define a dynamic repeatable zone for richer page layouts.

Before Reading

This article uses a Link Resolver to help render Rich Text & Title fields. To learn more about this, check out the Link Resolving page.

Example 1

Here is a simple example that shows you how to add slices to your templates. In this example, we have two slices: a text slice and an image gallery slice.

Text slice

The "text" slice is simple and only contains one field, which is non-repeatable.

Primary

non-repeatable

- A Rich Text field with the API ID of "text"

Items

repeatable

None

The "image_gallery" slice contains both repeatable and non-repeatable fields.

Primary

non-repeatable

- A Title field with the API ID of "name_of_the_gallery"

Items

repeatable

- An Image field with the API ID of "gallery_image"

- A Title field with the API ID of "image_caption"

Integration

Here is an example of how to integrate these slices into a blog post. In this case, the Slice object has the API ID of body.

Copy
import React, { Fragment } from 'react'
import { graphql } from 'gatsby'
import { RichText } from 'prismic-reactjs'
import { linkResolver } from '@prismicio/gatsby-source-prismic-graphql'

const Page = ({ data }) => {
  const prismicContent = data.prismic.allPages.edges[0]
  if (!prismicContent) return null

  const blogContent = prismicContent.node.body.map((slice, index) => {
    // Render the right markup for the given slice type

    // Text Slice
    if (slice.type === 'text') {
      return (
        <Fragment key={`slice-${index}`}>
          {RichText.render(slice.primary.text, linkResolver)}
        </Fragment>
      )

    // Image Gallery Slice
    } if (slice.type === 'image_gallery') {
      const galleryContent = slice.fields.map((gallery, galleryIndex) => (
        <span key={`gallery-item-${galleryIndex}`}>
          <img
            src={gallery.gallery_image.url}
            alt={gallery.gallery_image.alt}
          />
          <p className="image-caption">
            {RichText.asText(gallery.image_caption)}
          </p>
        </span>
      ))
      return (
        <div className="image-gallery" key={`slice-${index}`}>
          <h2 className="gallery-title">
            {RichText.asText(slice.primary.name_of_the_gallery)}
          </h2>
          {galleryContent}
        </div>
      )

    // Return null by default
    }
    return null
  })

  return (
    <div className="blog-content">
      {blogContent}
    </div>
  )
}

export const query = graphql`
  query {
    prismic {
      allPages(uid: "test-page") {
        edges {
          node {
            body {
              ... on PRISMIC_PageBodyImage_gallery {
                type
                label
                primary {
                  name_of_the_gallery
                }
                fields {
                  gallery_image
                  image_caption
                }
              }
              ... on PRISMIC_PageBodyText {
                type
                label
                primary {
                  text
                }
              }
            }
          }
        }
      }
    }
  }
`

export default Page

Example 2

The following is a more advanced example that shows how to use Slices for a landing page. In this example, the Slice choices are FAQ question/answers, featured items, and text sections.

FAQ slice

The "faq" slice is takes advantage of both the repeatable and non-repeatable slice sections.

Primary

non-repeatable

- A Title field with the API ID of "faq_title"

Items

repeatable

- A Title field with the API ID of "question"

- A Rich Text field with the API ID of "answer"

The "featured_items" slice contains a repeatable set of an image, title, and summary field.

Primary

non-repeatable

None

Items

repeatable

- An Image field with the API ID of "image"

- A Title field with the API ID of "title"

- A Rich Text field with the API ID of "summary"

Text slice

The "text" slice contains only a Rich Text field in the non-repeatable section.

Primary

non-repeatable

- A Rich Text field with the API ID of "text"

Items

repeatable

None

Integration

Here is an example of how to integrate these slices into a landing page. In this example the Slice Zone has the API ID body.

Copy
import React from 'react'
import { graphql } from 'gatsby'
import { RichText } from 'prismic-reactjs'
import { linkResolver } from '@prismicio/gatsby-source-prismic-graphql'

const Page = ({ data }) => {
  const prismicContent = data.prismic.allPages.edges[0]
  if (!prismicContent) return null

  const pageContent = prismicContent.node.body.map((slice, index) => {
    // Render the right markup for the given slice type

    // FAQ Slice
    if (slice.type === 'faq') {
      const faqContent = slice.fields.map((faq, faqIndex) => (
        <div key={`faq-item-${faqIndex}`}>
          {RichText.render(faq.question, linkResolver)}
          {RichText.render(faq.answer, linkResolver)}
        </div>
      ))
      return (
        <div className="faq" key={`slice-${index}`}>
          {RichText.render(slice.primary.faq_title, linkResolver)}
          {faqContent}
        </div>
      )

    // Featured Items Slice
    } if (slice.type === 'featured_items') {
      const featuredContent = slice.fields.map((featuredItem, featuredIndex) => (
        <div key={`featured-item-${featuredIndex}`}>
          <img src={featuredItem.image.url} alt={featuredItem.image.alt} />
          {RichText.render(featuredItem.title, linkResolver)}
          {RichText.render(featuredItem.summary, linkResolver)}
        </div>
      ))
      return (
        <div className="featured-items" key={`slice-${index}`}>
          {featuredContent}
        </div>
      )

    // Text Slice
    } if (slice.type === 'text') {
      return (
        <div className="text" key={`slice-${index}`}>
          {RichText.render(slice.primary.text, linkResolver)}
        </div>
      )

    // Return null by default
    }
    return null
  })

  return (
    <div className="page-content">
      {pageContent}
    </div>
  )
}

export const query = graphql`
  query {
    prismic {
      allPages(uid: "test-page") {
        edges {
          node {
            _linkType
            body {
              ... on PRISMIC_PageBodyText {
                type
                label
                primary {
                  text
                }
              }
              ... on PRISMIC_PageBodyFaq {
                type
                label
                fields {
                  question
                  answer
                }
                primary {
                  faq_title
                }
              }
              ... on PRISMIC_PageBodyFeatured_items {
                type
                label
                fields {
                  image
                  title
                  summary
                }
              }
            }
          }
        }
      }
    }
  }
`

export default Page