NextJS RSC Structured Text render mismatch

In our project we have a structuredtext field that has a inline record link to an other model.

When querying the graphql server this is the response that i got:

"mainDescription": {
        "value": {
          "schema": "dast",
          "document": {
            "type": "root",
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "span",
                    "value": "Hello"
                  }
                ]
              },
              {
                "type": "paragraph",
                "children": [
                  {
                    "item": "175921359",
                    "type": "inlineItem"
                  }
                ]
              }
            ]
          }
        },
        "links": [
          {
            "__typename": "NotificationRecord",
            "id": "175921359",
            "statusType": "warning",
            "description": {
              "value": {
                "schema": "dast",
                "document": {
                  "type": "root",
                  "children": [
                    {
                      "type": "paragraph",
                      "children": [
                        {
                          "type": "span",
                          "value": "This is a warning message"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        ],
        "blocks": []
      },

In my NextJS AppRouter server component I have this code to render the structedtext with help of the StructuredText component of react-datocms:

import { NotificationFragment } from "@/lib/client";
import type { StructuredTextGraphQlResponse } from "react-datocms";
import { StructuredText } from "react-datocms/structured-text";
import { Message, MessageType } from "ui";

type DatoStructuredTextProps = {
 data: StructuredTextGraphQlResponse;
};

export const DatoStructuredText = ({ data }: DatoStructuredTextProps) => {
 return (
   <StructuredText
     data={data}
     renderBlock={() => <></>}
     renderInlineRecord={({ record }) => {
       switch (record.__typename) {
         case "NotificationRecord":
           const parsed = record as NotificationFragment;
           return (
             <Message
               message={
                 <DatoStructuredText
                   data={parsed.description}
                 />
               }
               type={record.statusType as MessageType}
               showIcon={false}
             />
           );
         default:
           return null;
       }
     }}
   />
 );
};

This is my Message component:

export const Message = ({
  message,
  showIcon = true,
  type = "info",
  iconSize = "lg",
}: MessageProps) => {
  const { base } = styles({ type });

  return (
    <div className={base()}>
      {showIcon && (
        <FontAwesomeIcon icon={typeToIconMap[type]} size={iconSize} />
      )}
      {message}
    </div>
  );
};

The StructuredText component wraps the message component in a

tag, then renders a div tag and inside that a

tag again since we use the StructuredText component again to render the message.

To my HTML looks like this:

<p>
  <div>
    <p>NEW - required by law</p>
  </div>
</p>

I found this already:

So my question is how can I overcome this issue with the StructedText render? I basicly want to skip some <p> tags if it is just for inline record or blocks

Kind regards,
Kasper

Hello @k.sprengers and welcome to the community!

The issue comes from this passage right here:

A <p> tag can never wrap a div, and will generate that error if it does.

Since spans have to always be inside a paragraph, your Message component cannot have a div inside of it, perhaps you can replace the div with a paragraph with a different syling?

Or, if you’d like to conditionally render paragraph nodes, you can create a customRenderRule for paragraphs, where you check the child nodes, and if they contain a Message block, you don’t render them (or render them as divs instead). You can overide those default render rules for nodes as documented right here: react-datocms/docs/structured-text.md at master Β· datocms/react-datocms Β· GitHub

Just as the documented isHeading utility is provided the same package also exposes the isParagraph utility to customize paragraph nodes

1 Like