Issue with displaying images in a block on Next.js application resolved with the help of custom portable text and Sanity's image URL documentation.

6 replies
Last updated: Sep 5, 2023
Hi, I got this message while trying to display images I uploaded from a block(rich text). Only the text is shown but not the images. Can someone help me with this? I would appreciate it. I'm using react,nextjs. react-portable-text, typescript
AI Update

I can help you with this! The issue you're experiencing is a common one when working with Portable Text in React. When you're using react-portable-text, images aren't automatically rendered - you need to define custom serializers (components) to tell the library how to handle image blocks.

The first thing to note is that react-portable-text is actually an older, community-maintained library. I'd recommend switching to @portabletext/react, which is the official library from Sanity and has better support for TypeScript and Next.js.

First, install the official library:

npm install @portabletext/react @sanity/image-url

Then create custom serializers for your images:

import { PortableText } from '@portabletext/react'
import imageUrlBuilder from '@sanity/image-url'
import { SanityImageSource } from '@sanity/image-url/lib/types/types'

// Configure your image builder
const builder = imageUrlBuilder({
  projectId: 'your-project-id',
  dataset: 'your-dataset'
})

function urlFor(source: SanityImageSource) {
  return builder.image(source)
}

// Define your custom components
const ptComponents = {
  types: {
    image: ({ value }: any) => {
      if (!value?.asset?._ref) {
        return null
      }
      return (
        <img
          src={urlFor(value).width(800).url()}
          alt={value.alt || ' '}
          loading="lazy"
        />
      )
    }
  }
}

// Use it in your component
export default function MyComponent({ content }: { content: any }) {
  return <PortableText value={content} components={ptComponents} />
}

With react-portable-text (Your Current Setup)

If you want to stick with react-portable-text, you need to add serializers:

import PortableText from 'react-portable-text'
import imageUrlBuilder from '@sanity/image-url'

const builder = imageUrlBuilder({
  projectId: 'your-project-id',
  dataset: 'your-dataset'
})

<PortableText
  content={yourContent}
  serializers={{
    image: ({ value }: any) => (
      <img
        src={builder.image(value).width(800).url()}
        alt={value.alt || ' '}
      />
    )
  }}
/>

Important Notes

  1. Install @sanity/image-url: You'll need this package to generate proper image URLs from Sanity's image references.

  2. Check your schema: Make sure your Portable Text field includes the image type:

    {
      name: 'body',
      type: 'array',
      of: [
        { type: 'block' },
        { type: 'image' }  // This is crucial!
      ]
    }
  3. The "unknown type image" warning means your serializer isn't being recognized. The custom component configuration above should fix this.

I'd strongly recommend migrating to @portabletext/react as it's the actively maintained solution with better TypeScript support and follows modern React patterns. The main API difference is that it uses value instead of node props in serializers, but it's more reliable for Next.js projects.

For more details on customizing Portable Text rendering, check out Sanity's comprehensive guide.

Yea so you need to have a custom portable text that renders something with the image type. Here is mine that I used for my Next.js application
Thanks for your answer, now it shows me the tag of the image but in the src to show the image the url appears like this "undefined"
You’ll probably need to use https://www.sanity.io/docs/image-url
Thank you very much, the problem has been solved. One question, what about the image quality? Only in the block the images look blurry.
There’s a .quality() option that you can add onto it, I believe it’s in that documentation I linked to. You can also adjust the width and height.
Right, thank you.

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?