@prismicio/react - v2
Overview
@prismicio/react
is the official Prismic package for creating web apps with Prismic and React.
Dependencies and requirements
This package can be used in projects that use React. It is compatible with React Server Components. It relies on @prismicio/client
as a peer dependency.
Since this is a general-purpose React library, it can be used in setups like Vite or in more advanced frameworks that use React like Next.js and Gatsby.
Installation
Add @prismicio/react
and its peer dependencies to your React project via the command line:
npm install @prismicio/react @prismicio/client
Components
@prismicio/react
provides a collection of components to render content from Prismic documents.
Here are all of the components and hooks:
<PrismicProvider>
import { PrismicProvider } from "@prismicio/react";
A React component to provide settings for Prismic’s React components, using React context. All @prismicio/react
components that are children of this one will receive the specified options as defaults.
<PrismicProvider client={client}>
{children}
</PrismicProvider>
<PrismicProvider>
accepts the following props:
| An initialized Prismic API client from the @prismicio/client package. If provided, all client hooks use this client automatically. |
| A function that takes a document from Prismic as an argument and returns the URL path for that document. See the link resolver documentation. |
| A map or function that returns a React component for a given rich text element. See the |
| A component for handling internal links. See the section on |
| A component for handling external links. See the section on |
<PrismicRichText>
import { PrismicRichText } from "prismicio/react";
A React component that renders content from a Prismic rich text or title field.
By default, HTML elements are rendered for each piece of content. For example, a heading1
block will render an <h1>
HTML element. Links will use <PrismicLink>
by default.
<PrismicRichText field={document.data.myRichTextField} />
A fallback
prop can be provided to define what to render when the rich text or title field is empty. If a fallback
prop is not provided, null
is rendered by default for an empty field.
<PrismicRichText
field={document.data.myRichTextField}
fallback={<p>No content</p>}
/>
This component returns a React fragment with no wrapping element around the content. If you need a wrapper, add a component around <PrismicRichText>
.
<article>
<PrismicRichText field={document.data.myRichTextField} />
</article>
To customize the components that are rendered for each block type, provide a map or function that returns a component to the components
prop.
<PrismicRichText
field={document.data.myRichTextField}
components={{
heading1: ({ children }) => (
<Heading>{children}</Heading>
),
paragraph: ({ children }) => (
<p className="paragraph">{children}</p>
),
}}
/>
To globally customize <PrismicRichText>
, create a wrapper component with your default props. Use the wrapper component in place of @prismicio/react
’s version.
import { PrismicRichText as BasePrismicRichText } from "@prismicio/react";
const defaultComponents = {
heading1: ({ children }) => (
<h1 className="font-bold text-3xl">{children}</h1>
),
};
export const PrismicRichText = ({
components,
...props
}) => {
return (
<BasePrismicRichText
components={{ ...defaultComponents, ...components }}
{...props}
/>
);
};
If a different component needs to be rendered for a specific instance of <PrismicRichText>
, a components
prop can be provided to override the shared component mapping.
Here’s an example that uses all the available field keys for the components
object:
<PrismicRichText
field={document.data.myRichTextField}
components={{
heading1: ({ children, key }) => (
<h1 key={key}>{children}</h1>
),
heading2: ({ children, key }) => (
<h2 key={key}>{children}</h2>
),
heading3: ({ children, key }) => (
<h3 key={key}>{children}</h3>
),
heading4: ({ children, key }) => (
<h4 key={key}>{children}</h4>
),
heading5: ({ children, key }) => (
<h5 key={key}>{children}</h5>
),
heading6: ({ children, key }) => (
<h6 key={key}>{children}</h6>
),
paragraph: ({ children, key }) => (
<p key={key}>{children}</p>
),
preformatted: ({ node, key }) => (
<pre key={key}>{node.text}</pre>
),
strong: ({ children, key }) => (
<strong key={key}>{children}</strong>
),
em: ({ children, key }) => (
<em key={key}>{children}</em>
),
listItem: ({ children, key }) => (
<li key={key}>{children}</li>
),
oListItem: ({ children, key }) => (
<li key={key}>{children}</li>
),
list: ({ children, key }) => (
<ul key={key}>{children}</ul>
),
oList: ({ children, key }) => (
<ol key={key}>{children}</ol>
),
image: ({ node, key }) => {
const img = (
<img
src={node.url}
alt={node.alt ?? undefined}
data-copyright={
node.copyright ? node.copyright : undefined
}
/>
);
return (
<p key={key} className="block-img">
{node.linkTo ? (
<PrismicLink
linkResolver={args.linkResolver}
internalComponent={args.internalLinkComponent}
externalComponent={args.externalLinkComponent}
field={node.linkTo}
>
{img}
</PrismicLink>
) : (
img
)}
</p>
);
},
embed: ({ node, key }) => (
<div
key={key}
data-oembed={node.oembed.embed_url}
data-oembed-type={node.oembed.type}
data-oembed-provider={node.oembed.provider_name}
dangerouslySetInnerHTML={{
__html: node.oembed.html ?? "",
}}
/>
),
hyperlink: ({ node, children, key }) => (
<PrismicLink
key={key}
field={node.data}
linkResolver={args.linkResolver}
internalComponent={args.internalLinkComponent}
externalComponent={args.externalLinkComponent}
>
{children}
</PrismicLink>
),
label: ({ node, children, key }) => (
<span key={key} className={node.data.label}>
{children}
</span>
),
span: ({ text, key }) => {
const result: React.ReactNode[] = [];
let i = 0;
for (const line of text.split("\n")) {
if (i > 0) {
result.push(<br key={`${i}__break`} />);
}
result.push(
<React.Fragment key={`${i}__line`}>
{line}
</React.Fragment>,
);
i++;
}
return (
<React.Fragment key={key}>{result}</React.Fragment>
);
},
}}
/>
<PrismicText>
import { PrismicText } from "@prismicio/react";
React component that renders content from a Prismic rich text or title field as plain text.
<PrismicText field={document.data.myTitleField} />
A fallback
prop can be provided to define what to render when the rich text or title field is empty. If a fallback
prop is not given, null
is rendered by default for an empty field.
<PrismicText
field={document.data.myTitleField}
fallback="Untitled"
/>
This component returns a React fragment with no wrapping element around the content. If you need a wrapper, add a component around <PrismicRichText>
.
<h1>
<PrismicText field={document.data.myTitleField} />
</h1>
<PrismicLink>
import { PrismicLink } from "@prismicio/react";
React component that renders a link from a Prismic link field or a Prismic document.
It automatically resolves a field’s link to a URL and renders the link’s display text. It also applies the correct target
and rel
props if “Open in new tab” is enabled for the field. It also applies directly a link label if the property text
is present
// With default text property
<PrismicNextLink field={document.data.example_link} />
// Overriding with custom children
<PrismicNextLink field={document.data.label_link}>Click Me</PrismicNextLink>
To link to a document, use the document prop in place of the field prop.
<PrismicLink document={document}>Click me</PrismicLink>
By default, an <a>
HTML element is rendered for all links. If your React app requires a special <Link>
component for internal links, such as one from react-router-dom
, a component can be provided to the internalComponent
prop. That component will automatically be rendered for internal links.
<PrismicLink
field={document.data.myLinkField}
internalComponent={Link}
/>
The component for external links can similarly be overridden using the externalComponent
prop.
<PrismicLink
field={document.data.myLinkField}
externalComponent={(props) => (
<a className="external" {...props} />
)}
/>
To globally customize <PrismicLink>
, create a wrapper component with your default props. Use the wrapper component in place of @prismicio/react
’s version.
import { PrismicLink as BasePrismicLink } from "@prismicio/react";
const InternalLink = (props) => {
return <a className="internal" {...props} />;
};
export const PrismicLink = (props) => {
return (
<BasePrismicLink
internalComponent={InternalLink}
{...props}
/>
);
};
If your app uses the route resolver when querying for documents, providing a link resolver is optional. If your app does not use a route resolver or requires overriding a document’s URL in specific cases, a link resolver can be provided using the linkResolver
prop.
<PrismicLink
field={document.data.myLinkField}
linkResolver={linkResolver}
/>
<PrismicImage>
import { PrismicImage } from "@prismicio/react";
React component that renders an optimized image from a Prismic image field. The rendered <img>
element contains a srcset
with image URLs for common viewport widths.
<PrismicImage field={doc.data.myImageField} />
The image CDN which Prismic serves all images through, imgix, allows image transformations using URL parameters. imgix URL parameters can be provided to <PrismicImage>
using the imgixParams
prop.
// Renders a grayscale image
<PrismicImage
field={doc.data.myImageField}
imgixParams={{ sat: -100 }}
/>
See imgix’s Image URL API Reference for a full list of the available parameters, including saturation changes, cropping, and blurring.
The component automatically applies the image field’s alt text to the rendered <img>
element. To customize the alt text, use the alt
prop.
<PrismicImage field={doc.data.imageField} alt="" />
To provide a fallback alt text to be used if the image field does not contain alt text, use the fallbackAlt
prop.
<PrismicImage field={doc.data.imageField} fallbackAlt="" />
Note: The alt
and fallbackAlt
props only accept an empty string (''
) to let you declare an image as decorative. Any other value is invalid. See the “alt
must be an empty string” article for more details.
By default, <PrismicImage>
will use the following widths in its srcset
attribute: 640, 750, 828, 1080, 1200, 1920, 2048, 3840
. To override these widths, use the widths
prop.
<PrismicImage
field={doc.data.imageField}
widths={[400, 800, 1600]}
/>
To use a pixel density-based srcset
instead, pass a set of pixel densities to the pixelDensities
prop.
<PrismicImage
field={doc.data.imageField}
pixelDensities={[2, 4]}
/>
To use the built-in set of good default pixel densities, pass pixelDensities='defaults'
to the component. The component uses [1, 2, 3]
as its default pixel densities.
<PrismicImage
field={doc.data.imageField}
pixelDensities="defaults"
/>
<SliceZone>
import { SliceZone } from "@prismicio/react";
React component that renders content from a Prismic slice zone using React components for each type of slice.
For example, if a slice zone contains a Text slice followed by an Images slice, <SliceZone>
will render <TextSlice>
and <ImagesSlice>
in a list.
<SliceZone
slices={document.data.body}
components={{
text: TextSlice,
images: ImagesSlice,
}}
/>
Alongside the slices
prop, an object of slice type IDs (for example: “text”) mapped to its React component (for example: <TextSlice>
) should be provided to the components
prop.
Slice components receive four props:
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>
’s context prop.
A slice component could look like this:
function TextSlice({ slice }) {
return (
<section>
<PrismicRichText field={slice.primary.text} />
</section>
);
}
If you have data that needs to be shared with all slice components, provide a value to the context
prop. The data will be passed to each slice component as a context
prop.
<SliceZone
slices={document.data.body}
components={{
text: TextSlice,
images: ImagesSlice,
}}
context={{ foo: "bar" }}
/>
You can then consume the prop in any slice component defined in the components
array.
function TextSlice({ slice, context }) {
return (
<section>
<PrismicRichText field={slice.primary.text} />
<p>{context.foo}</p>
</section>
);
}
By default, a “TODO” component will be rendered with a warning if a component is not provided for a slice type. To override the default component, provide a component to the defaultComponent
prop. The default component is passed the same props listed above.
<SliceZone
slices={document.data.body}
defaultComponent={() => null}
/>
The default “TODO” component will not be rendered in production (i.e. when process.env.NODE_ENV
is production
).
This component returns a React fragment with no wrapping element around the list of slice components. If you need a wrapper, add a component around <SliceZone>
.
<article>
<SliceZone
slices={document.data.body}
components={{
text: TextSlice,
images: ImagesSlice,
}}
/>
</article>
To optimize the performance of <SliceZone>
, prefer defining the components
prop using a variable defined outside the component.
const components = {
text: TextSlice,
images: ImagesSlice,
};
function Page() {
return (
<SliceZone
slices={document.data.body}
components={components}
/>
);
}
<PrismicToolbar>
import { PrismicToolbar } from "@prismicio/react";
React component that injects the Prismic Toolbar into the app.
This component can be placed anywhere in the React tree. The Prismic Toolbar script will be appended to the end of the app’s <body>
element.
<PrismicToolbar repositoryName="repo-name" />
If your repository requires the legacy Prismic Toolbar, provide a type
prop to use the legacy script. By default, type
is set to "new"
.
<PrismicToolbar repositoryName="repo-name" type="legacy" />
Hooks
Each query method from a Prismic client, such as getAllByType()
or getSingle()
, is provided as a hook.
const client = prismic.createClient("example-prismic-repo");
const [documents] = useAllPrismicDocumentsByType("page", {
client,
});
const [settingsDocument] = useSinglePrismicDocument(
"settings",
{ client },
);
All hooks accept a client
parameter which should be passed a Prismic client created with @prismicio/client
. See the @prismicio/client Technical Reference for configuration options.
const client = prismic.createClient("example-prismic-repo");
const [page] = usePrismicDocumentByUID("page", "home", {
client,
});
Hooks return the fetching state in addition to the query result. This allows you to render, for example, a “loading” interface while the client is fetching results.
const [documents, { state, error }] =
useAllPrismicDocumentsByType("page", {
client,
});
state
can be one of the following values:
"idle"
: The hook is waiting to query the repository."loading"
: The hook is querying the repository."loaded"
: The hook is done querying the repository."failed"
: The hook failed to query the repository.
error
will contain a PrismicError
object from @prismic/client
if the hook fails to query the repository. The hook will be in the "failed"
state.
If a hook requires specific parameters or a different client, they can be provided as an object in the last argument.
const client = prismic.createClient("example-prismic-repo");
const [documents] = useAllPrismicDocumentsByType("page", {
client,
lang: "fr-fr",
});
All query hooks
Here are all of the components and hooks:
usePrismicDocuments() | See client.get() |
useFirstPrismicDocument() | See client.getFirst() |
| See |
usePrismicDocumentByID() | See client.getByID() |
| See |
usePrismicDocumentByUID() | See client.getByUID() |
| See |
useSinglePrismicDocument() | See client.getSingle() |
| See |
| See client.getByTag() |
| See |
| See |
usePrismicClient()
A hook that returns the Prismic client provided to <PrismicProvider>
at the root of your React app.
const client = usePrismicClient();
Use this hook to call methods directly on the client. For example, getting a list of all tags can be performed like this:
function MyComponent() {
const [tags, setTags] = React.useState();
const client = usePrismicClient();
React.useEffect(() => {
client.getTags().then((tags) => setTags(tags));
}, [client]);
}
usePrismicPreviewResolver(params)
A hook that returns the URL of a previewed document during a preview session. This hook should be used on your React app’s preview resolver page.
const [resolvedURL, { state, error }] =
usePrismicPreviewResolver();
The hook will automatically read the preview session’s URL parameters to resolve the previewed document’s URL.
If you pass a navigate option, the hook will automatically redirect the browser to the resolved URL. The navigate option should be a function that accepts a URL string and redirects the browser. Popular client-side routing libraries like React Router provide this function to you.
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
usePrismicPreviewResolver({ navigate });