(Astro & React) The Structured Text document contains an 'itemLink' node, but no 'renderLinkToRecord' prop is specified! (edited title)

This is the code from blog page

import { Image } from "react-datocms";
import Date from "../../components/date";
import getBlogPost from "request:getBlogPost";
import PostBody from "../../components/post-body";
import MainLayout from "../../layouts/MainLayout.astro";
import getAllBlogpostSlugs from "request:getAllBlogpostSlugs";

export const prerender = false;

const { slug } = Astro.params;
const post = await getBlogPost(slug);

export async function getStaticPaths() {
  const data = await getAllBlogpostSlugs();
  const pathsArray = data.map((slug) => {
    return { params: { slug } };
  });
  return pathsArray;
}
console.log(slug);
---

<style>
  /* adjust imported posts */
  .prose {
    margin-top: -130px;
  }
</style>

<MainLayout title={post.title} seo={post.seo}>
  <div class="blog-header-section">
    <div class="blog-post-header">
      <div class="w-layout-blockcontainer container-1200 w-container">
        <div class="wrapper-112p">
          <div class="flex-row-space-between align-top gap-64 wrap-tablet">
            <div>
              <h1 class="heading-3">
                {post.title}
              </h1>

              <div class="blog-post__meta">
                <div>
                  {
                    post.category.map((category, index) => (
                      <a href={`/blog/${category.slug}`} class="tag-link">
                        {index ? ", " : ""}
                        {category.name}
                      </a>
                    ))
                  }
                </div>
                <h2 class="body-text mb-0">
                  {post.date && <Date dateString={post.date} />}
                </h2>
              </div>
            </div>

            <div class="blog-post-header__blog-author">
              {
                post.author && post.author.image && (
                  <Image
                    lazyLoad={false}
                    data={post.author.image.responsiveImage}
                    className="blog-author-photo"
                    client:visible
                  />
                )
              }
              <div>
                <h6 class="body-text small-headline mb-0">
                  {post.author && post.author.name}
                </h6>
                <div class="body-text mb-0">
                  {post.author && post.author.title}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div class="page-gradient-wrapper">
    <section class="section-112p">
      <div class="w-layout-blockcontainer container-1200 w-container">
        <div class="blog-post__content body-text">
          <PostBody content={post.body} />
        </div>
      </div>
    </section>
  </div>
</MainLayout>

This is code for the post body

import { StructuredText } from "react-datocms";
import BlockPostImage from "./blocks/blockPostImage";
import BlockRelatedItems from "./blocks/blockRelatedItems";
import BlockMissing from "./blocks/blockMissing";

export default function PostBody({ content }) {
  return (
    <div className="max-w-2xl mx-auto">
      <div className="prose prose-lg prose-blue">
        <StructuredText
          data={content}
          renderBlock={({ record }) => {
            switch (record._modelApiKey) {
              case "block_post_image":
                return <BlockPostImage record={record} />;
              case "related_item":
                return <BlockRelatedItems record={record} />;
              case "text":
                return <Text item={item} />;
              default:
                return <BlockMissing record={record} />;
            }
          }}
        />
      </div>
    </div>
  );
}

Here is the error

├─ /blog/compliance/15/index.html (+66ms)
  ├─ /blog/news/index.html (+69ms)
  └─ /blog/news/2/index.html (+67ms)
▶ src/pages/blog/[slug].astro

node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

RenderError: The Structured Text document contains an 'itemLink' node, but no 'renderLinkToRecord' prop is specified!
    at new RenderError (/Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/datocms-structured-text-utils@2.0.4/node_modules/datocms-structured-text-utils/dist/cjs/render.js:29:28)
    at file:///Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/react-datocms@4.1.3_graphql@16.8.1_react@18.2.0/node_modules/react-datocms/dist/esm/StructuredText/index.js:55:27
    at Object.apply (/Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/datocms-structured-text-utils@2.0.4/node_modules/datocms-structured-text-utils/dist/cjs/render.js:40:16)
    at transformNode (/Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/datocms-structured-text-utils@2.0.4/node_modules/datocms-structured-text-utils/dist/cjs/render.js:56:34)
    at /Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/datocms-structured-text-utils@2.0.4/node_modules/datocms-structured-text-utils/dist/cjs/render.js:48:20
    at Array.map (<anonymous>)
    at transformNode (/Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/datocms-structured-text-utils@2.0.4/node_modules/datocms-structured-text-utils/dist/cjs/render.js:47:14)
    at /Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/datocms-structured-text-utils@2.0.4/node_modules/datocms-structured-text-utils/dist/cjs/render.js:48:20
    at Array.map (<anonymous>)
    at transformNode (/Users/derrickthreatt/Documents/GitHub/retrograde-resonance/node_modules/.pnpm/datocms-structured-text-utils@2.0.4/node_modules/datocms-structured-text-utils/dist/cjs/render.js:47:14) {
  node: {
    item: 'GF6fhYr2TRe90NbFI0iLyQ',
    meta: [ { id: 'rel', value: 'noopener' } ],
    type: 'itemLink',
    children: [ { type: 'span', value: 'application of techniques' } ]
  }
}

Node.js v18.15.0

Here is the entry in the structured block in DatoCMS

Hey @dthreatt,

You have to tell the <StructuredText/> component how to render your linked records using the renderLinkToRecord prop, like this:

  renderLinkToRecord={({ record, children, transformedMeta }) => {
          switch (record.__typename) {
            case 'TeamMemberRecord':
              return (
                <a {...transformedMeta} href={`/team/${record.slug}`}>
                  {children}
                </a>
              );
            default:
              return null;
          }
        }}

Link to the documentation: react-datocms/docs/structured-text.md at master · datocms/react-datocms · GitHub

Does that help?

Yes that resolved it…thanks so much. We also had to add that data to the GraphQL call.

import { StructuredText } from "react-datocms";
import BlockPostImage from "./blocks/blockPostImage";
import BlockRelatedItems from "./blocks/blockRelatedItems";
import BlockMissing from "./blocks/blockMissing";

export default function PostBody({ content }) {
  return (
    <div className="max-w-2xl mx-auto">
      <div className="prose prose-lg prose-blue">
        <StructuredText
          data={content}
          renderBlock={({ record }) => {
            switch (record._modelApiKey) {
              case "block_post_image":
                return <BlockPostImage record={record} />;
              case "related_item":
                return <BlockRelatedItems record={record} />;
              case "text":
                return <Text item={item} />;
              default:
                return <BlockMissing record={record} />;
            }
          }}
          renderLinkToRecord={({ record, children, transformedMeta }) => {
            switch (record.__typename) {
              case 'PageRecord':
                return (
                  <a class="link-blue" {...transformedMeta} href={`/${record.slug}`}>
                    {children}
                  </a>
                );
              case 'ProductRecord':
                return (
                  <a class="link-blue" {...transformedMeta} href={`/${record.slug}`}>
                    {children}
                  </a>
                );
              case 'ResourceRecord':
                return (
                  <a class="link-blue" {...transformedMeta} href={record.externalUrl}>
                    {children}
                  </a>
                );
              case 'BlogpostRecord':
                return (
                  <a class="link-blue" {...transformedMeta} href={`/blog/${record.slug}`}>
                    {children}
                  </a>
                );
              default:
                return null;
            }
          }}
          renderInlineRecord={({ record }) => {
            switch (record.__typename) {
              case 'PageRecord':
                return (
                  <a class="link-blue" href={`/${record.slug}`}>
                    {record.title}
                  </a>
                );
              case 'ProductRecord':
                return (
                  <a class="link-blue" href={`/${record.slug}`}>
                    {record.title}
                  </a>
                );
              case 'ResourceRecord':
                return (
                  <a class="link-blue" href={record.externalUrl}>
                    {record.title}
                  </a>
                );
              case 'BlogpostRecord':
                return (
                  <a class="link-blue" href={`/blog/${record.slug}`}>
                    {record.title}
                  </a>
                );
              default:
                return null;
            }
          }}
        />
      </div>
    </div>
  );
}
1 Like