@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:

client

An initialized Prismic API client from the @prismicio/client package. If provided, all client hooks use this client automatically.

linkResolver

A function that takes a document from Prismic as an argument and returns the URL path for that document. See the link resolver documentation.

richTextComponents

A map or function that returns a React component for a given rich text element. See the **<PrismicRichText>** section for more detail.

internalLinkComponent

A component for handling internal links. See the section on **<PrismicLink>** for more detail.

externalLinkComponent

A component for handling external links. See the section on **<PrismicLink>** for more detail.

<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.

src/components/PrismicRichText.tsx
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>
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.

src/components/PrismicLink.tsx
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()

useAllPrismicDocumentsDangerously()

See client.dangerouslyGetAll()

usePrismicDocumentByID()See client.getByID()

usePrismicDocumentsByIDs()


useAllPrismicDocumentsByIDs()

See client.getByIDs(), client.getAllByIDs()

usePrismicDocumentByUID()See client.getByUID()

usePrismicDocumentsByUIDs()


useAllPrismicDocumentsByUIDs()

See client.getByUIDs(), client.getAllByUIDs()

useSinglePrismicDocument()See client.getSingle()

usePrismicDocumentsByType()


useAllPrismicDocumentsByType()

See client.getByType(), client.getAllByType()

usePrismicDocumentsByTag()


useAllPrismicDocumentsByTag()

See client.getByTag()

usePrismicDocumentsBySomeTags()


useAllPrismicDocumentsBySomeTags()

See client.getBySomeTags(), client.getAllBySomeTags()

usePrismicDocumentsByEveryTag()


useAllPrismicDocumentsByEveryTag()

See client.getByEveryTag(), client.getAllByEveryTag()

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 });