Portable Text Lists Rendering as P Tags Instead of UL/LI Elements

23 replies
Last updated: Dec 2, 2025
Afternoon! I am struggling to parse lists via portable text. Im using the react-portable-text package and seem to be able to add custom classNames to h2's without any issues. However all of the bulleted list items in my unordered list are rendering to the dom as p tags and I cant seem to get the serializer to impact them. Any tips are appreciated! https://jmp.sh/S4NZ2qn
AI Update

Based on the thread you've linked and the context around your issue, the key problem is that you need to query the _raw version of your Portable Text field in GraphQL for lists to render properly. This is true for both react-portable-text and the official packages.

The Solution: Use _raw in Your GraphQL Query

When querying Portable Text through Sanity's GraphQL API, you need to use the _raw field (e.g., _rawBody instead of just body). The non-raw version doesn't include the proper structure for list items, which is why they're rendering as <p> tags.

Change your query from:

{
  body
}

To:

{
  _rawBody
}

Then pass _rawBody to your Portable Text component. This was confirmed as the solution by someone who had the exact same issue you're experiencing.

About react-portable-text

The react-portable-text package is a third-party library, not officially maintained by Sanity. While it can work once you use the _raw field, I'd recommend switching to the official @portabletext/react package for better long-term support and more predictable behavior with lists and other complex structures.

Better Long-Term Solution: Switch to @portabletext/react

The official package handles lists properly and has cleaner customization options:

npm install @portabletext/react

Usage example:

import { PortableText } from '@portabletext/react'

const components = {
  block: {
    h2: ({children}) => <h2 className="your-h2-class">{children}</h2>
  },
  list: {
    bullet: ({children}) => <ul className="your-list-class">{children}</ul>,
    number: ({children}) => <ol className="your-ordered-list-class">{children}</ol>
  },
  listItem: {
    bullet: ({children}) => <li>{children}</li>
  }
}

<PortableText value={yourRawContent} components={components} />

Note that it uses value (not content or blocks) and components (not serializers). You can find more details in the official Portable Text React documentation and the ultimate customization guide.

The bottom line: Query _rawBody (or _raw + your field name) in GraphQL, and your lists should render correctly regardless of which package you're using!

Show original thread
23 replies

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?