Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Using PortableText with defined types in components for a schema with a hero object inside a parent Portable Text array.

24 replies
Last updated: Feb 17, 2023
Hello!I am trying to se PortableText for this query:
I don't know how can I define the
hero
and
content
types in my components options.To be more specific, I want to define
hero
and
content
as JSX elements
Feb 17, 2023, 5:51 PM
What do your components look like so far?
Feb 17, 2023, 6:03 PM
  const components = {
    types: {
      hero: {
        home: <Main />
      }
    }
  }
return (
 <PortableText  components={components} value={homepage} />
)
Feb 17, 2023, 6:04 PM
I get as an error : Unknown block type "hero.home", specify a component for it in the
components.types
prop
Feb 17, 2023, 6:04 PM
I don't know how to define "hero.home" as a type
Feb 17, 2023, 6:04 PM
homepage
contains all the fields in the screenshot
Feb 17, 2023, 6:08 PM
Got it. What does the schema for that look like?
Feb 17, 2023, 6:33 PM
/schemas/documents/homepage.ts

 defineField({
      name: 'hero',
      title: 'Hero',
      type: 'hero.home',
      group: 'editorial',
    }),

/schemas/objects/hero/home.ts

export default defineField({
  name: 'hero.home',
  title: 'Home hero',
  type: 'object',
  fields: [
    // Title
    defineField({
      // name: 'title',
      // title: 'Title',
      // type: 'text',
      // rows: 3,
      name: 'titleBlock',
      title: 'Title Block',
      type: 'array',
      of: [
        {
          type: 'block',
          marks: {
            decorators: [
              { title: 'Strong', value: 'strong' },
              { title: 'Emphasis', value: 'em' },
              { title: 'Code', value: 'code' },
              {
                title: 'Highlight',
                value: 'highlight',
                icon: HighlightIcon,
                component: HighlightDecorator
              }
            ]
          }
        }
      ]
    }),
    // Link
    defineField({
      name: 'links',
      title: 'Link',
      type: 'array',
      of: [{type: 'linkInternal'}, {type: 'linkExternal'}],
      validation: (Rule) => Rule.max(1),
    }),
    // Content
    defineField({
      name: 'content',
      title: 'Content',
      type: 'array',
      validation: (Rule) => Rule.max(1),
      of: [
        {
          name: 'productWithVariant',
          title: 'Product with variant',
          type: 'productWithVariant',
        },
        {
          name: 'imageWithProductHotspots',
          title: 'Image',
          type: 'imageWithProductHotspots',
        },
      ],
    }),
  ],
})

Feb 17, 2023, 6:36 PM
Is that
hero.home
object inside of a parent Portable Text array?
Feb 17, 2023, 7:20 PM
yes, if you see the
_type
of hero is
hero.home
Feb 17, 2023, 7:21 PM
Sorry, I mean have you put that entire
hero.home
block inside of another Portable Text array? Iā€™m trying to figure out why it would be trying to serialize the container.
Feb 17, 2023, 7:24 PM
I am not sure I did understand your question šŸ˜žThough, if I let the
components
in PortableText empty and pass that query in the screenshot as
value
.This is what I receive eventually :

Unknown block type "home", specify a component for it in the `components.types` prop``
Feb 17, 2023, 7:29 PM
Thiss is the value I am passing
Feb 17, 2023, 7:30 PM
Is there a way to define these types
hero, modules, seo
in one portable text
Feb 17, 2023, 9:03 PM
yes
{
 title: "Portable Text Field",
 name: "article",
 type: "array",
 of: [
    {type: "block"}, 
    {type: "hero"}, 
    {type: "modules"}, 
    {type: "seo"}
  ],
},
Feb 17, 2023, 9:11 PM
this will create an insert tab in your portable text wysiwyg interface with all those components.
Feb 17, 2023, 9:12 PM
this is how your suppose to handle that. then in your portable text client component youd create a serializer for each component.
Feb 17, 2023, 9:14 PM
Would it impossible to achieve something similar without adding these components in the block editor?
Feb 17, 2023, 9:14 PM
to achieve the exact same thing youd probably have to make an array with each component including a component with a portable text field. that way you can add in components or text fields and order them as if it were using one portable text field.
Feb 17, 2023, 9:16 PM
Can you please give me an example if that possible šŸ˜„
Feb 17, 2023, 9:19 PM
     {
      title: "Components",
      name: "components",
      type: "array",
      of: [
        {
          type: "reference",
          to: {type: "article"},
        },
        {
          type: "reference",
          to: {type: "hero"},
        },
        .... etc
      ],
    },
Feb 17, 2023, 9:20 PM
this way you can add more of each item and arrange them in any order. which is essentially the exact same thing a portable text field would do when you insert a new document or object type.
Feb 17, 2023, 9:22 PM
Oooh, so I can use PortableText even if the schema doesn't necessarily have to be
block
as a field type?
Feb 17, 2023, 9:22 PM
youd create a new document type or object type where one field is
block
to achieve this. call that
article
which is the first entry in that example above.
Feb 17, 2023, 9:24 PM
Oh I understand! thank you so much!
Feb 17, 2023, 9:25 PM

Sanityā€“ build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?