How to render Sanity rich text (Portable Text) array in React component?

10 replies
Last updated: May 19, 2022
hi guys,
I have this piece of content type that is a rich text:

   {
            name: "info",
            title: "Info",
            type: "array",
            of: [
                {
                title: "Block",
                type: "block",
                styles: [{title: "Normal", value: "normal"}],
                lists: [],
            },
and I need to render this on my homepage, how do I render this in here:

export async function getStaticProps ({preview = false}) {
  const product = await getClient(preview).fetch(groq`
    *[_type == 'product']{
      name,
      sku,
      image,
      finish,
      info,
    }[0]`)

  return {
      props: {
        product,
      },
    }
}
AI Update

You'll need to use the @portabletext/react library to render that rich text content in your Next.js app. Here's how to set it up:

First, install the library:

npm install @portabletext/react

Then in your component, import and use the PortableText component:

import { PortableText } from '@portabletext/react'

export default function Product({ product }) {
  return (
    <div>
      <h1>{product.name}</h1>
      <PortableText value={product.info} />
    </div>
  )
}

export async function getStaticProps ({ preview = false }) {
  const product = await getClient(preview).fetch(groq`
    *[_type == 'product']{
      name,
      sku,
      image,
      finish,
      info,
    }[0]`)

  return {
    props: {
      product,
    },
  }
}

The basic implementation is that simple! The PortableText component takes your info array and automatically renders it as proper HTML.

If you want to customize how the content looks, you can pass custom components:

const components = {
  block: {
    normal: ({children}) => <p className="my-custom-paragraph">{children}</p>,
  },
  marks: {
    strong: ({children}) => <strong className="font-bold">{children}</strong>,
  }
}

<PortableText value={product.info} components={components} />

Note: If you're using the older @sanity/block-content-to-react library anywhere, you should migrate to @portabletext/react as it's the modern, officially supported version. The main difference is that the old node prop is now called value.

Show original thread
10 replies
You’ll need to use the @portabletext/react library. There is a good guide on getting started. Essentially, you’ll want to pass
<http://props.product.info|props.product.info>
to the component.
<PortableText
  value={props.product.info}
  components={/* optional object of custom components to use */}
/>
it throws me a server error: ReferenceError: props is not defined
I cannot help without seeing the code. I assume you’re destructuring your props or something? You might need to adapt the code snippets I share with you. 😅
i did it like this now but its not rendering .
const richTextcomp = (props) => {<PortableText value={props.product.info}/>}
It does show up in the console
You’re not returning anything from this function.
PortableText
is a React component, so you would use it just like any other React component.
you mean like this?
export async function getStaticProps ({preview = false}) {
  const product = await getClient(preview).fetch(groq`
    *[_type == 'product']{
      name,
      sku,
      image,
      finish,
      info,
    }[0]`)

const PortableText = (props) => {<PortableText value={props.product.info}/>}

  return {
      props: {
        product,
      },
    }
}

export default Home
Well, kind of. But there are a few things that are not working here:1. You’re shadowing the name
PortableText
, which won’t work. If you want to wrap your
PortableText
usage in another component, pick a different name.
PortableText
is what you import from the library.2. You’re not returning anything from that component. You either need a
return
statement or you need to remove these curly braces.Ultimately, you use it like this (again the code might need to get adjusted to work in your project, it’s just an example):

const Home = ({ product }) => {
  return (
    <div><PortableText value={product.info} /></div>
  )
}
ooooh I get it now I just needed to ad this
<div><PortableText value={product.info} /></div>
between my other lines in my div thanks! this works
Nice. 😊

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?