Portable Text code block error: forEach not returning component in Next.js

5 replies
Last updated: Nov 29, 2025
Good evening. I’ve hit a bit of a sticking point with portable text in Next.js and I’m wondering if anyone has attempted this here.
TLDR: I’m getting an error that reads
Error: code(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

I came by this pull request that suggested a method to handle
<code>
in react.

https://github.com/portabletext/react-portabletext/pull/8/commits/46154520f029a429d30b4964ebcec91269581231
From there I looked into
npm
react-syntax-highlighter
as a nice way to serve up a code block in my project.

https://github.com/react-syntax-highlighter/react-syntax-highlighter
Having read the sanity docs on the topic

https://www.sanity.io/docs/presenting-block-text
I came up with an implementation that looks something like this…

JSON Data


"data": {
    "allPost": [
      {
        "contentRaw": [
           {
            "_key": "5978aa8a8ae9",
            "_type": "code",
            "code": "if (1 + 1 === 2) return 'Success'";
            "language": "javascript"
            },
         ]
      }
JS


...
<div className={utilStyles.postData}>
   <PortableText
      value={currPost[0].contentRaw}
      components={components}
   />

...
JS components

  const components = {
    types: {
      code: () => {
        contentRaw.forEach((block) => {
          if (block.hasOwnProperty('code')) {
            return (
              <SyntaxHighlighter language={block.language} style={nightOwl}>
                {block.code}
              </SyntaxHighlighter>
            );
          }
        });
      },
    },
  };

My expectation is that for each code type in the contentRaw JSON array (there are actually many), I should be returning out the styling from the component… instead I get the mentioned error
Error: code(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

Might anyone be able to see where I have mis-stepped?
AI Update

I can see the issue in your code! The problem is that you're using forEach inside your component function, which doesn't return anything. forEach always returns undefined, so React is complaining that nothing was returned from your render function.

The @portabletext/react library passes the block data directly to your custom component as props, so you don't need to iterate through contentRaw at all. Here's the corrected implementation:

const components = {
  types: {
    code: ({value}) => {
      return (
        <SyntaxHighlighter language={value.language} style={nightOwl}>
          {value.code}
        </SyntaxHighlighter>
      );
    },
  },
};

The key changes:

  1. Accept the value prop - This contains your code block data (the object with code, language, _key, etc.)
  2. Return directly - No need to loop through anything, just return the component
  3. Access properties from value - Use value.code and value.language instead of iterating

The @portabletext/react library automatically handles the iteration through your contentRaw array and calls your custom component for each block that matches the type. When it encounters a block with _type: "code", it will call your code component and pass that specific block as the value prop.

Your component will be called once for each code block in your content, so if you have multiple code blocks in contentRaw, each one will render separately with its own data.

If you want to add the filename property that Sanity's code input supports, you could extend it like this:

const components = {
  types: {
    code: ({value}) => {
      return (
        <div>
          {value.filename && <div className="code-filename">{value.filename}</div>}
          <SyntaxHighlighter language={value.language || 'text'} style={nightOwl}>
            {value.code}
          </SyntaxHighlighter>
        </div>
      );
    },
  },
};

This pattern works for any custom type in Portable Text - the component receives the block's data as value, along with other useful props like isInline if you need them. You can learn more about custom serializers and component structure in the Sanity guides.

Show original thread
5 replies

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.

Was this answer helpful?