Why does PortableText need dataset and projectId props if sanity.json exists?

8 replies
Last updated: Feb 18, 2022
Hi, I am using
PortableText
but I am wondering why is the dataset, projectId necessary when you hava projectId and dataset in the sanity.json file.

<PortableText
            dataset={process.env.NEXT_PUBLIC_SANITY_DATASET!}
            projectId={process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!}
            content={post.body}
            serializers={{
              h1: (props: any) => (
                <h1 className="text-2xl font-bold my-5" {...props} />
              ),
              h2: (props: any) => (
                <h2 className="text-xl font-bold my-5" {...props} />
              ),
              h3: (props: any) => (
                <h3 className="text-lg font-bold my-5" {...props} />
              ),
              h4: (props: any) => (
                <h4 className="text-md font-bold my-5" {...props} />
              ),
              blockquote: (props: any) => (
                <blockquote
                  className="text-xl text-red-300 font-bold my-5"
                  {...props}
                />
              ),
              li: ({ children }: any) => (
                <li className="ml-4 list-disc">{children}</li>
              ),
              link: ({ href, children }: any) => (
                <a href={href} className="text-blue-500 hover:underline">
                  {children}
                </a>
              ),
            }}
          />

AI Update

Good question! The projectId and dataset props on the PortableText component are specifically needed for rendering images (and other assets like files) that are embedded in your Portable Text content.

When your Portable Text contains images, the component needs to construct proper image URLs using Sanity's image URL builder. To generate these URLs, it needs to know which Sanity project and dataset to pull the images from. The component can't automatically read from your sanity.json or sanity.config.ts file because it's a standalone React component that doesn't have access to your Sanity configuration.

Here's what's happening behind the scenes:

When you have an image block in your Portable Text, the component needs to transform the image reference (which is just metadata) into an actual URL like:

https://cdn.sanity.io/images/{projectId}/{dataset}/{imageId}-{dimensions}.{format}

However, if your Portable Text content doesn't contain any images or file references, you technically don't need to pass these props. But it's good practice to include them anyway in case you add images to your content later.

If you want to avoid repeating these props everywhere, you have a few options:

  1. Create a wrapper component that automatically passes these values:
// components/MyPortableText.tsx
import { PortableText } from '@portabletext/react'

export function MyPortableText({ content, serializers }) {
  return (
    <PortableText
      value={content}
      components={serializers}
      projectId={process.env.NEXT_PUBLIC_SANITY_PROJECT_ID}
      dataset={process.env.NEXT_PUBLIC_SANITY_DATASET}
    />
  )
}
  1. Use a custom image serializer with your own image URL builder, where you configure the projectId and dataset once in your Sanity client configuration.

Note: The prop should be value={post.body} (not content) and components (not serializers) if you're using the modern @portabletext/react library, though it looks like your code might be using an older version where those prop names were different.

Show original thread
8 replies
Hi Geoff. So, the props for each serializer is not required? Good to know!
Not all props are required—correct.
Good to know! Thanks
user A
Removing the {…props} from each serializer results in not being visible on the front-end side.
You should be able to remove
dataset={process.env.NEXT_PUBLIC_SANITY_DATASET!}
and
projectId={process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!}
.
user A
I’ve notice that when removing dataset and projectId there where I have one image inside the data body array Next js crashes. Because there is a image in the body of the Sanity article.

Error: You must either:
- Pass
projectId
and
dataset
to the block renderer

- Materialize images to include the
url
field.
After removing the projectId and dataset it works if the post has no image in the body. But having only
body
inside the query will cause Nextjs to crash. I’ve replaced it with the following and managed to fix the issue.

body[]{
 ...,
 asset -> {
 ...,
 "_key": _id
 }
},

user A
is that kind of a spread operator, and does the [] make it an array of content, where you pick the asset to display.
Those props will be required in order to handle images unless you handle images in your serializer. Here’s one I’m using, for example:

types: {
  image: ({ node: { caption, credit, asset, alt, width } }) => (
    <figure className="inline-image">
      <img src={urlFor(asset).width(width).fit('max').url()} alt={alt} />
      <figcaption>
        {caption && <span className="float-left">{caption}</span>}
        {credit && <i className="float-right">Photo credit: {credit}</i>}
      </figcaption>
    </figure>
  ),
  // ... other stuff ...
}

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?