How to render text from block type field in Sanity?

22 replies
Last updated: Dec 14, 2021
Hi! I’m trying to understand how to render block types. I have a
description
field inside a schema that’s a block type. However I’m unsure how to target the actual
text
property that comes back, so it’s just displaying the number of “arrays” inside the block. what am I doing wrong?
AI Update

It sounds like you're seeing something like [object Object] or array counts instead of the actual text content from your block field. This is a common issue when trying to render Portable Text (Sanity's block content format) directly without using a proper renderer.

Block content in Sanity isn't just a simple string—it's a structured array of objects that describe the content, formatting, and other rich text features. You can't just display it like {description} in your template.

The solution is to use @portabletext/react (the official library for rendering block content):

npm install @portabletext/react

Then in your component:

import { PortableText } from '@portabletext/react'

function MyComponent({ data }) {
  return (
    <div>
      <PortableText value={data.description} />
    </div>
  )
}

The PortableText component will automatically render the text, handling paragraphs, bold/italic formatting, lists, and other standard elements.

If you need custom styling or want to render special block types, you can pass custom components:

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

<PortableText value={data.description} components={components} />

If you're using the older @sanity/block-content-to-react library, note that it's deprecated—you should migrate to @portabletext/react. The main difference is that the prop names changed (like node becoming value).

Check out the ultimate guide for customizing Portable Text for more advanced use cases!

Show original thread
22 replies
the
0 1
in light gray is supposed to be the text i have in sanity studio
Hey User! You'll need to use something to serialize your portable text blocks here. What are you using for your frontend?
next js!
Got it! Do you have next-sanity installed?
Got it! Do you have next-sanity installed?
user M
yes I do have it installed!
Perfect! You'll need to pass your block content into a Portable Text component. If you check out the usage here , in the
lib/sanity.js
file, there's an import of
createPortableTextComponent
. It'll get configured something like the following:
import {
  createImageUrlBuilder,
  createPortableTextComponent,
} from 'next-sanity'

const config = {
  /**
   * Find your project ID and dataset in `sanity.json` in your studio project.
   * These are considered "public", but you can use environment variables
   * if you want differ between local dev and production.
   *
   * <https://nextjs.org/docs/basic-features/environment-variables>
   **/
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || 'production',
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
  apiVersion: '2021-10-21', // Learn more: <https://www.sanity.io/docs/api-versioning>
  /**
   * Set useCdn to `false` if your application require the freshest possible
   * data always (potentially slightly slower and a bit more expensive).
   * Authenticated request (like preview) will always bypass the CDN
   **/
  useCdn: process.env.NODE_ENV === 'production',
}

/**
 * Set up a helper function for generating Image URLs with only the asset reference data in your documents.
 * Read more: <https://www.sanity.io/docs/image-url>
 **/
export const urlFor = (source) => createImageUrlBuilder(config).image(source)

// Set up Portable Text serialization
export const PortableText = createPortableTextComponent({
  ...config,
  // Serializers passed to @sanity/block-content-to-react
  // (<https://github.com/sanity-io/block-content-to-react>)
  serializers: {},
})
You'll see an example of passing data to that
<PortableText>
component here .
this is wonderful thank you so much
user M
!
user M
I meant to circle back on this. It doesn’t seem like the rich text styles are being applied? Is there an extra step I need to take?
Styles like colors, pacing, or font won't be carried over from the Portable Text Editor in your Studio. You would need to use CSS to style it on your frontend. 🙂
oh so if I have something like this in the Portable Text editor it won’t be carried over?
Things like bold or headings will be carried over, since those have semantic meaning. If they're not showing up, it's likely that you have a CSS reset that's removing their styling.
ooohhh yeah I definitely do hahah
i have a css-reset file 😆
dang it
Lol, yeah that got me the first time, too!
so this is a dumb question but how would I apply styles to the portable text 🥲
so this is a dumb question but how would I apply styles to the portable text 🥲
ex: how do I tell the Portable Text to add
margin-bottom: 1rem
so that each paragraph has space
(my plan B is to just get rid of the css-reset file)
So, you can:a. override
the default serializers to return an entirely custom elementb. wrap the
<BlockContent />
in a wrapper div that you can then target, like so:
In your App:

<div className='wrapper'>
  <BlockContent ... />
</div>

---

In your CSS:

wrapper h2 {
 //your style
}
c. directly apply style to all of a given element in your app like so:

h2 {
  //your style
}

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?