question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RFC: @prismicio/react refresh

See original GitHub issue

Overview

This request for comments (RFC) presents a collection of React components and hooks to make presenting and fetching Prismic content easy and extendable. Some of the described components are updates to the existing prismic-reactjs library, while others are new.

These ideas have been developed as a result of real-world use in different environments including within agencies and in-house development teams.

The proposals defined in this RFC are designed for all React users. Some are general enough to be used in frameworks (such as Next.js and Gatsby), while others are recommended for non-framework use. Each section includes a “Designed to be used with” label to identify for whom it is designed.

Background Information

prismic-reactjs currently includes the following exports:

Components

  • <RichText>: Render a Rich Text field into React Components

Functions

  • RichText.asText(): Convert a Rich Text field into a text string
  • Date(): Parse a Date field into a Date object
  • Link.url(): Convert a Link field into a URL

This API combines a React Component with a collection of helper functions from @prismicio/helpers and @prismicio/richtext. The combination of components and functions leads to non-idiomatic React code, mixing JSX (e.g. <RichText>) with JavaScript expressions (e.g. {RichText.asText()}).

Components provide a way to encapsulate functionality. The current library does not fully utilize this concept. Link.url(), for example, could be integrated into a <Link> component which performs the URL transformation implicitly. Because Link.url() is simply a re-exported helper from @prismicio/helpers, users could import that library instead if such lower-level functionality is needed.

Proposal

The following components and hooks make for a more robust React integration with Prismic.

  • <PrismicProvider>: Central configuration.
  • <SliceZone>: Render Slices in a Slice Zone.
  • <RichText>: Render a Rich Text field into React Components.
  • <RichTextAsText>: Render a Rich Text field as text.
  • <PrismicLink>: Render a Link field as a router-specific Link or anchor element.
  • <PrismicToolbar>: Add the Prismic Toolbar script.
  • usePrismicDocument(), et al.: Prismic document fetching hooks.

Each component and hook is described below.

Rename to @prismicio/react

To mirror recent efforts to streamline Prismic’s library naming, the library should be renamed from prismic-reactjs to @prismicio/react.

The following Prismic libraries also follow this convention:

  • @prismicio/client
  • @prismicio/helpers
  • @prismicio/richtext
  • @prismicio/types

<PrismicProvider>

Designed to be used with: React w/o a framework, Next.js, Gatsby

This Context Provider sets up app-wide configuration for the library’s components and hooks. It can contain an app’s @prismicio/client instance, Link Resolver, Rich Text components, and a router-specific Link component. See the following component and hook descriptions to learn how they are used.

Using the provider is optional. If it is not used, components and hooks can be configured where they are used.

In cases where multiple repositories are used to gather content, or when location-specific overrides are needed, values provided to the provider have a lower priority than configuration provided to a component or hook directly.

import * as prismic from '@prismicio/client'
import { PrismicProvider, PrismicLink } from '@prismicio/react'
import { Link } from 'react-router-dom'

import { linkResolver } from '../linkResolver'
import { Heading } from './Heading'

const endpoint = prismic.getEndpoint('qwerty')
const client = prismic.createClient(endpoint)

const richTextComponents = {
  h1: 'h2',
  h2: Heading,
  h3: (props) => <Heading as="h4" {...props} />,
}

const App = ({ children }) => {
  return (
    <PrismicProvider
      client={client}
      linkResolver={linkResolver}
      richTextComponents={richTextComponents}
      internalLinkComponent={Link}
    >
      {children}
    </PrismicProvider>
  )
}

<SliceZone>

Designed to be used with: React w/o a framework, Next.js, Gatsby

See the dedicated <SliceZone> RFC: https://github.com/prismicio/prismic-reactjs/issues/86

<SliceZone
  slices={document.data.body}
  components={{
    foo: FooSlice,
    bar: BarSlice,
  }}
/>

<RichText>

Designed to be used with: React w/o a framework, Next.js, Gatsby

This component renders an HTML representation of a Rich Text field. It automatically converts links using a provided Link Resolver. By default, it renders a standard set of HTML elements (e.g. Heading 1 becomes <h1>), but can be overridden using a list of components.

The component to be rendered can be provided in several ways:

  1. As a string denoting an HTML element (e.g. "h2").
  2. As a direct reference to a React component (e.g. Heading).
  3. As an inline React component definition (e.g. (props) => <Heading as="h4" {...props} />)

This provides users an easy and flexible way to override the rendered components. This replaces the HTML Serializer concept with a simpler approach without removing capabilities.

<RichText
  field={document.data.content}
  linkResolver={linkResolver}
  components={{
    heading1: 'h2',
    heading2: Heading,
    heading3: (props) => <Heading as="h4" {...props} />,
    hyperlink: (props) => <PrismicLink internalComponent={Link} {...props} />,
  }}
/>

If <PrismicProvider> is used and configured with a richTextComponents prop, it will be used as <RichText>'s components prop. If a components prop is provided to <RichText>, it will take priority over the prop provided to <PrismicProvider>. The same behavior is included for linkResolver.

<RichText field={document.data.content} />

<RichTextAsText>

Designed to be used with: React w/o a framework, Next.js, Gatsby

This component renders a text representation of a Rich Text field. It serves as the “non-rich” counterpart to the <RichText> component as it strips all formatting and HTML representations within the field’s contents.

<RichTextAsText field={document.data.content} />

Since the output is a string, no customization aside from the field prop is necessary.

<PrismicLink>

Designed to be used with: React w/o a framework, Next.js, Gatsby

This component renders a link from a Prismic Link field. It supports internal and external URLs and can render the appropriate component accordingly. If a link is internal to an app, the app may require a special <Link> component to be rendered rather than an <a> element. <PrismicLink> will automatically switch to that component as needed.

<PrismicLink
  field={document.data.link}
  linkResolver={linkResolver}
  internalComponent={Link}
  externalComponent="a"
>
  Learn More
</PrismicLink>

If the link is configured with target="_blank", which can be set within the Prismic editor, rel="noopener noreferrer" will be added for improved security. Users can opt-out by providing their own rel prop.

For <RichText> and Gatsby compatibility, PrismicLink can take an href directly. The href prop accepts a URL string that has already gone through the app’s Link Resolver or an external URL. The URL can be internal or external with the same automatic adaption described previously.

// Renders externalComponent
<PrismicLink href="https://example.com">
  Learn More
</PrismicLink>

// Renders internalComponent
<PrismicLink href="/about">
  Learn More
</PrismicLink>

If <PrismicProvider> is used and configured with an internalLinkComponent prop, it will be used as <PrismicLink>'s internalComponent prop. If an internalComponent prop is provided to <PrismicLink>, it will take priority over the prop provided to <PrismicProvider>. The same behavior is included for externalComponent.

<PrismicLink field={document.data.link}>
  Learn More
</PrismicLink>

<PrismicToolbar>

Designed to be used with: React w/o a framework, Next.js, Gatsby

This component makes it convenient to add the Prismic Toolbar to an app. It automatically generates the correct script URL and includes the recommended configuration.

<PrismicToolbar repositoryName="qwerty" type="new" />

The output would be equivalent to the following HTML.

<script
  src="https://static.cdn.prismic.io/prismic.js?repo=qwerty&new=true"
  defer="true"
/>

usePrismicDocument(), et al.

Designed to be used with: React w/o a framework

A collection of React hooks, including usePrismicDocuments(), usePrismicDocumentByID(), and usePrismicDocumentsByType(), queries the Prismic REST API for content from a Prismic repository.

The API mirrors that of the @prismicio/client library in hook form. It handles different states automatically, such as loading states and data persistence between re-renders. API parameters, such as lang and orderings, are provided as each hook’s last parameter, just like using the client directly.

The following hooks fetch one or more documents. They return Prismic’s paginated API responses which can be helpful when displaying paginated content.

  • usePrismicDocuments()
  • usePrismicDocumentsByIDs()
  • usePrismicDocumentsByTag()
  • usePrismicDocumentsByTags()
  • usePrismicDocumentsByType()

The following list of hooks is a variation of the previous list. These hooks automatically fetch all documents from a paginated response and may make multiple network requests in order to fetch all matching documents.

  • useAllPrismicDocuments()
  • useAllPrismicDocumentsByIDs()
  • useAllPrismicDocumentsByTag()
  • useAllPrismicDocumentsByTags()
  • useAllPrismicDocumentsByType()

The following hooks return one document.

  • usePrismicDocumentByID()
  • usePrismicDocumentByUID()
  • useFirstPrismicDocument(): Returns only the first matching document
  • useSinglePrismicDocument(): Returns a singleton document of a given type

All hooks return the following data shape:

import * as prismic from '@prismicio/client'
import { usePrismicDocument } from '@prismicio/react'

const endpoint = prismic.getEndpoint('qwerty')
const client = prismic.createClient(endpoint)

const MyComponent = () => {
  const { data, isLoading, error } = usePrismicDocumentByUID('page', 'home', {
    client
  })

  return <span>My component</span>
}
  • data: The paginated API response or document, depending on the hook. During a loading state, this prop is null.
  • isLoading: true when the hook is fetching data, false otherwise.
  • error: The error if the query fails.

The @prismicio/client instance is provided using the client option in the hooks’ last parameter.

import * as prismic from '@prismicio/client'
import { usePrismicDocumentByUID } from '@prismicio/react'

const endpoint = prismic.getEndpoint('qwerty')
const client = prismic.createClient(endpoint)

const MyComponent = () => {
  const { data, isLoading, error } = usePrismicDocumentByUID('page', 'home', {
    client,
  })

  return <span>My component</span>
}

If <PrismicProvider> is used and configured with a client prop, it will be used as the client option. If a client option is provided to a hook, it will take priority over the prop provided to <PrismicProvider>.

How to provide feedback

This is a public request for comments on the proposed ideas. If you have any feedback or suggestions, please feel free to reply below.

We would like to hear from potential users of these ideas whether the ideas positively or negatively impact workflows. If you have any additional ideas as well, please share them here.

Everything posted here is open for feedback and is not final. Development may have already begun by the time you are reading this, but please do not let that stop you from providing feedback.

Thank you!


A note on an image component

An image component is intentionally not included in this RFC. If such a component were to be included, it would perform the following:

  • Progressive loading (including the “blur-up” technique)
  • Automatic srcSet generation
  • Automatic aspect ratio sizing to prevent content reflows

Users using React as part of a framework, like Next.js or Gatsby, already have access to deeply integrated image components with those features. They are widely used and well tested with a dedicated team behind them.

Users using React directly, including those using Create React App, can use Imgix’s official React component, react-imgix, with the same benefits.

As such, a <PrismicImage> component is not included in the RFC. We can, however, provide proper integrations with React frameworks through gatsby-source-prismic and @prismicio/next (does not exist at the time of writing). We can also provide guidance for non-framework users.

If you feel this is not the correct approach, please comment below.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:4
  • Comments:15 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
angeloashmorecommented, Dec 3, 2021

@prismicio/react@v2.0.0 was just published (see #97) so I’m going to close this issue.

Thanks for your feedback, everyone! 🎉

1reaction
angeloashmorecommented, Aug 23, 2021
Read more comments on GitHub >

github_iconTop Results From Across the Web

Prismic on Twitter: "React devs! We're thinking about the future ...
We're thinking about the future of our React integration with ... RFC: @prismicio/react refresh · Issue #92 · prismicio/prismic-react.
Read more >
@prismicio/react Technical Reference - Documentation - Prismic
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 ......
Read more >
@prismicio/react - npm
React components and hooks to fetch and present Prismic content. Latest version: 2.5.1, last published: 2 days ago.
Read more >
prismicio - Bountysource
Hi Prismic folks :) I'm trying to use the nodejs package with its bundled d.ts files. However, types are not properly imported when...
Read more >
Target _Blank For Rich Text Prismic On Nextjs - ADocLib
prismicreactjs repo issues. RFC: @prismicio/react refresh. Overview. This request for comments RFC presents a collection of React components and.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found