😎 Discover cool tips and tricks for customization in our next Developer Deep Dive virtual event - sign up now!

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?