Using PortableText with defined types in components for a schema with a hero object inside a parent Portable Text array.
Based on your question, it sounds like you have custom block types called hero and content in your Portable Text schema, and you want to define how they render as JSX elements in your React components.
Here's how you can define custom block types as JSX elements using the @portabletext/react library:
import { PortableText } from '@portabletext/react'
// Define your custom components
const HeroComponent = ({ value }) => {
return (
<div className="hero">
<h1>{value.title}</h1>
<p>{value.description}</p>
{/* Access other fields from your hero block */}
</div>
)
}
const ContentComponent = ({ value }) => {
return (
<section className="content-section">
{/* Render whatever fields your content block has */}
<div>{value.body}</div>
</section>
)
}
// Define the components object
const ptComponents = {
types: {
hero: HeroComponent,
content: ContentComponent,
// Add other custom block types here
}
}
// Use it in your render
function MyPage({ portableTextData }) {
return (
<PortableText
value={portableTextData}
components={ptComponents}
/>
)
}The key points from the Portable Text documentation:
- Custom block components receive a
valueprop (notnode- that's the old API) containing all the data from your block - Define them in the
typesobject within thecomponentsprop - Return JSX directly from your component functions
If you're getting an "Unknown block type" error, make sure:
- The type names in your
components.typesobject match exactly what you defined in your Sanity schema - You've included all custom block types that appear in your content
You can also check out this comprehensive guide on customizing Portable Text which covers the full flow from schema definition to React rendering.
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.