Template Content
This technology has no Slice Machine integration
This framework has no integration with Prismic's developer tool, Slice Machine. You can still build a Prismic website with this technology by using Prismic's Legacy Builder. However, if you're starting a new project with Prismic, we strongly recommend using a technology that integrates with Slice Machine: Next.js or Nuxt.
On this page, you'll learn how to template content from the Prismic API in your React application.
Before you proceed
This article assumes that you have queried your API and saved the document
object in a variable named document
, as described in Fetch Data in React.
Content from Prismic comes in different types. Some are simple fields, like numbers or booleans. Others are structured fields, like titles, rich text, and links.
Simple field types can be used directly in your application:
<span>{document.data.example_number}</span>
// <span>42</span>
The React integration includes special components for rendering structured fields. To render rich text, for instance, you can use <PrismicRichText>
:
<PrismicRichText field={document.data.example_title} />
// <h2>Hello World!</h2>
To get started, let's look at the structure of the API response.
When you use Prismic's query methods, you will see three different types of API responses:
- paginated responses, which return a
response
object - get-all responses, which return a
results
array - get-single responses, which return a
document
object
In fact, these are all part of the same structure: the response
object contains the results
array, in which each item is a document
object.
Here's more detail about what that each looks like:
When you perform a query using a paginated method, like usePrismicDocuments()
, you will get a response object, which contains pagination information and an array of up to 100 API results. Here is a truncated example of an API response containing some simple fields:
{
page: 1,
// Metadata for this query
// ...
results: [
{
uid: 'example-document',
// Metadata for this result
// ...
data: {
example_date: '2020-12-10',
example_timestamp: '2020-12-10T04:05:09+0000',
example_color: '#c7ab5d',
example_number: 74,
example_key_text: 'Example Key Text Value',
example_select: 'North',
example_boolean: true,
},
},
{...},
{...},
{...},
],
}
If you store the response in a variable called response
, you might access a single data point like this:
response.results[0].data.example_key_text
// Example Key Text Value
In React, you might use that like this:
<h3>{response.results[0].data.example_key_text</h3>
// <h3>Example Key Text Value</h3>
Or, you might loop over the results array and template each item, like this:
<ul>
{response.results.map((document) => (
<li key={document.id}>{document.data.example_key_text}</li>
))}
</ul>
The most important property on the response
object is the results
array.
When you perform a query using a use-all hook, such as useAllPrismicDocumentsByType()
, you will get a results
array containing all matching results. (If you use a paginated hook, it will contain a results
array with up to 100 documents.)
Here is a truncated example of an API response using useAllPrismicDocumentsByType()
:
[
{
uid: 'example-blog-post',
type: 'blog_post',
data: {
example_date: '2020-12-10',
example_color: '#c7ab5d',
example_key_text: 'Example Key Text Value',
},
},
{...},
{...},
{...},
]
If you store the response in a variable called results
, you might access a single data point like this:
results[0].data.example_key_text
// Example Key Text Value
In React, you might use it like this:
<h3>{results[0].data.example_key_text}</h3>
// <h3>Example Key Text Value</h3>
The results
array is an array of document
objects.
The query hooks useSinglePrismicDocument()
, usePrismicDocumentByUID()
, and usePrismicDocumentByID()
will return a document object, which contains the data for an individual document directly.
Here's a truncated example of the response for those queries:
{
uid: 'about',
// Metadata for this result
// ...
data: {
example_date: '2020-12-10',
example_color: '#c7ab5d',
example_key_text: 'Example Key Text Value',
},
}
With a single document query, you might access your data like this:
<h3>{document.data.example_key_text</h3>
// <h3>Example Key Text Value</h3>
The content for each Prismic field is delivered as either a simple primitive value or an object. The simple fields can be injected directly into your app since their value is either a string, a number, or a boolean. Here are the simple fields:
- Color
- Key text
- Number
- Select
- Boolean
- Date
- Timestamp
Here's an example of how to use the number field. You can template the other simple fields similarly.
<span>{document.data.example_number}</span>
// <span>42</span>
Retrieving the color field is similar. Here we can see how to do inline styling in React:
<h3 style={{ color: document.data.example_color }}>
My favorite color is Magenta
</h3>
// <h3 style={{ color: "#FF00FF" }}>
// My favorite color is Magenta
// </h3>
The date and timestamp fields from Prismic are strings. The raw response for each of these fields has the following formats:
- Date:
YYYY-MM-DD
- Timestamp:
YYYY-MM-DDTHH:MM:SS+0000
A package named @prismicio/client
provides a function to convert a date or timestamp field from Prismic into a JavaScript date object. This is helpful if you need to format the field value into something more user-friendly.
npm install @prismicio/client
With the client package installed, you can handle date and timestamp fields like in the following example.
import * as prismic from '@prismicio/client'
<p>{prismic.asDate(document.last_publication_date).getFullYear()}</p>
// <p>2021</p>
<time
datetime={prismic.asDate(document.data.example_timestamp).toISOString()}
>
{prismic.asDate(document.data.example_timestamp).toLocaleString()}
</time>
// <time datetime="2018-01-16T13:46:15.000Z">
// 01/16/2018, 1:46:15 PM
// </p>
The geopoint field is served as an object with two properties: latitude and longitude. This is the API response:
example_geopoint: {
latitude: 48.85392410000001,
longitude: 2.2913515000000073,
}
Here is an example of how to retrieve the latitude and longitude coordinates for a geopoint field.
<p>
My location is:
{document.data.example_geopoint.latitude.toFixed(2)}, {document.data.example_geopoint.longitude.toFixed(2)}
</p>
// <p>My location is: 48.85, 2.29</p>
example_embed: {
version: '1.0',
url: 'https://prismic.io',
type: 'link',
title: 'Make your website editable for the whole team - Prismic',
provider_name: null,
thumbnail_url: 'https://images.prismic.io/prismic-website/6e49007fec52f99861047cdd55b3ab190ea04295_dev-landing-page-image.png?auto=compress,format',
html: '<div data-type="unknown"><a href="https://prismic.io"><h1>Make your website editable for the whole team - Prismic</h1></div>',
embed_url: 'https://prismic.io/',
}
You can display an embed field using the html
property on the response. To render HTML, use React's dangerouslySetInnerHTML
prop. Learn more about dangerouslySetInnerHTML()
in the React documentation.
<div
dangerouslySetInnerHTML={{
__html: document.data.example_embed.html,
}}
/>
The <iframe>
may have a default height and width defined by the oEmbed provider. You can style the iframe's height and width in your global CSS:
iframe {
width: 100%;
height: auto;
}
The image field returns an object with data about the image, including a URL for your image (hosted on Prismic's servers) and alt text.
example_image: {
dimensions: {
width: 1920,
height: 1302,
},
alt: 'Pink flowers on a tree',
copyright: null,
url: 'https://images.prismic.io/sm-20201204-2/7d1fba99-5bec-4d59-b8eb-402706e2d36c_a-pril-62u95KgB49w-unsplash.jpg?auto=compress,format',
}
You can template an image using @prismicio/react
's <PrismicImage>
component. It renders an optimized image using Prismic’s built-in imgix integration.
import { PrismicImage } from '@prismicio/react'
<PrismicImage field={doc.data.example_image} />
Are you using Next.js or Gatsby?
If you are using Next.js or Gatsby, use @prismicio/next
's <PrismicNextImage>
component or Gatsby's gatsby-plugin-image
component instead.
You can apply image transformations using Prismic’s built-in imgix integration and the imgixParams
prop. This allows you to resize, crop, recolor, and more. See imgix’s URL API Reference for a full list of transformations.
The following example converts the image to grayscale with sat: -100
:
import { PrismicImage } from '@prismicio/next'
<PrismicImage field={doc.data.example_image} imgixParams={{ sat: -100 }} />
We recommend using <PrismicImage>
for most cases. However, you can also use the following helpers from @prismicio/client
to template images: asImageSrc()
, asImageWidthSrcSet()
, or asImagePixelDensitySrcSet()
.
For more information on <PrismicImage>
, see the @prismicio/react
technical reference.
Rich text and titles are delivered in an array that contains information about the text structure. Here's an example of the API response of the rich text field (title fields follow the same format).
example_rich_text: [
{
type: 'paragraph',
text: 'Example Rich Text Value',
spans: [
{
start: 8,
end: 17,
type: 'strong',
},
],
},
]
To render rich text and title fields, use the <PrismicRichText>
component. It will convert your rich text field to React components.
import { PrismicRichText } from '@prismicio/react'
<PrismicRichText field={document.data.example_rich_text} />
Using custom React components
To modify the output of a rich text field, provide a list of component
overrides to the e components prop. The list of components maps an element type to its React component. Here is an example using a custom component for paragraphs.
<PrismicRichText
field={document.data.example_rich_text}
components={{
paragraph: ({ children }) => <Text as="p">{children}</Text>,
}}
/>
Learn more about customizing rich text output in HTML Serializing.
The <PrismicText>
component will convert and output the text in the rich text or title field as a string.
import { PrismicText } from '@prismicio/react'
<PrismicText field={document.data.example_rich_text} />
The route resolver
Prismic does not know the routing of your React app (or if you're even using a router). You can tell Prismic the structure of your app with a route resolver when you create a client. (You should have already created a route resolver when you Installed Prismic in your app.) Prismic will then use that information to add a url
property to each document.
To learn more about creating URLs, see our article on the route resolver.
The link field allows you to link to an external webpage, an internal Prismic document, or an item in your Media Library (like a PDF). The content relationship field allows you to link specifically to an internal Prismic document.
Here's what a content relationship field looks like from the API (a link field takes a similar format). This field has an API ID example_content_relationship
, and it links to another document that has the UID another-document
and the type page
.
example_content_relationship: {
id: 'X9C65hEAAEFIAuLo',
type: 'page',
tags: [],
slug: 'another-document',
lang: 'en-us',
uid: 'another-document',
link_type: 'Document',
isBroken: false,
}
There are two things that you might want to do with a link:
- Link to another page or media item, internally or externally
- Pull in content from another document
Here's how to render a link from a link to web. Linking to another document from a content relationship field is performed the same way.
import { PrismicLink } from '@prismicio/react'
<PrismicLink field={document.data.example_link}>Example Link</PrismicLink>
The target
and rel
attributes will be set automatically if the link field is set to open the link in a new window.
Using a client-side router?
If you are using a client-side router like React Router, you may need to use a special link component for links internal to your app. <PrismicLink>
can automatically render a different component for internal links.
Here is an example of how you can provide a router link component:
import { PrismicLink } from '@prismicio/react'
import { Link } from 'react-router-dom'
<PrismicLink
field={response.data.example_rich_text}
internalComponent={({ href, ...props }) => <Link to={href} {...props} />}
/>
You can set this automatically for all <PrismicLink>
components by adding an internalLinkComponent
prop to your app's <PrismicProvider>
. Learn more in the @prismicio/react Technical Reference.
To pull in content from another document, you must fetch that content in your API query using the graphQuery
or fetchLinks
option. To use fetchLinks, the value should be:
- First, the API ID of the custom type is referenced in your content relationship field.
- Then, the API ID of the field that you want to retrieve.
If you have a custom type called blog
that includes a content relationship field called example_content_relationship
linked to a custom type called author
where you want to retrieve a field that has an API ID of author_name:
const [document] = usePrismicDocumentByUID('blog', 'my-blog-post', {
fetchLinks: ['author.author_name'],
})
Once you have adjusted your API query, the linked content will appear in a data
object nested in the link or content relationship field:
example_content_relationship: {
id: 'X9C65hEAAEFIAuLo',
type: 'blog',
tags: [],
slug: 'another-page-title',
lang: 'en-us',
uid: 'my-blog',
data: {
author_name: 'Jane Doe',
},
link_type: 'Document',
isBroken: false,
}
You can then render that content:
<strong>
By {document.data.example_content_relationship.data.author_name}
</strong>
// <strong>By Jane Doe</strong>
Slices vs groups
Slices and groups both allow you to create repeatable content templates. Groups are available in the static section of your document, and slices are available in the slice zone. The difference between groups and slices is that groups allow you to repeat a collection of fields, while slices let you repeat and mix different collections of fields.
A group field renders an array of content fields. Here's what the API response looks like for a hypothetical group field modeling a nav menu.
example_group: [
{
example_nav_label: 'Homepage',
example_nav_link: {...},
},
{
example_nav_label: 'About',
example_nav_link: {...},
},
]
To template a group field, use a .map()
function, like this:
<ul>
{document.data.example_group.map((item) => (
<li key={item.example_nav_label}>
<PrismicLink field={item.example_nav_link}>
{item.example_nav_label}
</PrismicLink>
</li>
))}
</ul>
In React, a key
prop should be given to the outer-most component in the .map()
function. Give it a value that will be unique among the group field's items.
Slices are repeatable, rearrangeable content sections. Learn more about slices in What is a Slice?
On the document
object, slices are stored in the body array, like so:
body: [
{
slice_type: 'text',
slice_label: null,
items: [{...}],
primary: {
rich_text: [
{
type: 'paragraph',
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
spans: [],
},
],
},
},
{
slice_type: 'image_gallery',
slice_label: null,
items: [{...}],
primary: {
gallery_title: [
{
type: 'heading1',
text: 'Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
spans: [],
},
],
},
},
]
Other names for the slice zone property
Most documents have one slice zone, stored in the body
property. However, you can change the name of this property in your custom type. And, if you add additional slice zones to a custom type, they will be named body1
, body2
, etc.
To render slices, use the <SliceZone>
component by passing a slice zone array and list of React components for each type of slice.
In the following example, we have a slice called text
and one called image_gallery
. Their components are being imported from another file in the project.
import { SliceZone } from '@prismicio/react'
import { TextSlice, ImageGallerySlice } from '../slices'
<SliceZone
slices={document.data.body}
components={{
text: TextSlice,
image_gallery: ImageGallerySlice,
}}
/>
Each slice component will receive the following props which can be used to display its content:
slice
: The slice object being rendered.index
: The index of the slice within the slice zone.slices
: The list of all slice objects in the slice zone.context
: Arbitrary data passed to the<SliceZone>
'scontext
prop.
A simple slice component could look like this:
function TextSlice({ slice }) {
return (
<section>
<PrismicRichText field={slice.primary.text} />
</section>
)
}
Can't find what you're looking for?
Need technical Support? Spot an error in the documentation? Get in touch with us on our Community Forum.