Error using @portabletext/react instead of @sanity/block-content-to-react

9 replies
Last updated: Feb 10, 2022
Just started using
@portabletext/react
in favor of
@sanity/block-content-to-react
. I had a custom serializer which worked correctly with the old sanity lib, but errors using the new portabletext lib. Here is the
types
section of the components I pass to the
PortableText
component:
  types: {
    /* eslint-disable-next-line react/display-name */
    authorReference: ({ node }) => <span>{node.author.name}</span>,
    mainImage: Figure,
    'github.gist': ({node}) => {
      const { id, file } = node;
      return <Gist id={id} file={file ? file : undefined }/>;
    }
  },
and this is the error I receive on the
github.gist
handler:
WebpackError: TypeError: Cannot destructure property 'id' of 'node' as it is undefined.
I can’t find anything special in the migration guide that I should do to make this work. It was working before…
🤔
AI Update

The issue you're experiencing is due to a key API change when migrating from @sanity/block-content-to-react to @portabletext/react. In the new library, the prop name changed from node to value.

Here's what you need to fix in your code:

types: {
  /* eslint-disable-next-line react/display-name */
  authorReference: ({ value }) => <span>{value.author.name}</span>, // changed from node to value
  mainImage: Figure,
  'github.gist': ({ value }) => { // changed from node to value
    const { id, file } = value;
    return <Gist id={id} file={file ? file : undefined} />;
  }
}

This is the primary breaking change when migrating from @sanity/block-content-to-react - all custom type components now receive their data through the value prop instead of node.

The destructuring was failing because node was undefined (since the library passes value instead), which is exactly what your error message indicated: "Cannot destructure property 'id' of 'node' as it is undefined."

Additionally, for marks/annotations (like links or custom text decorations), you'll access the data through value as well, while children remains the same for the wrapped content:

marks: {
  link: ({ value, children }) => <a href={value.href}>{children}</a>
}

The migration guide for @portabletext/react shows that this nodevalue change applies to all custom block types and annotations, making the API more consistent across the library.

Here is a sample value of a
github.gist
from one of my documents:
          {
            "_key": "257a2def14fd",
            "_type": "github.gist",
            "file": "run-app.sh",
            "id": "5995ea726914f280afb3"
          },
… and an error in my browser console when running the
dev
server:
Warning: Cannot update a component (`DevOverlay`) while rendering a different component (`githubGist`). To locate the bad setState() call inside `githubGist`, follow the stack trace as described in <https://reactjs.org/link/setstate-in-render>
githubGist@webpack-internal:///./src/components/serializers.js:32:18
PortableText@webpack-internal:///./node_modules/@portabletext/react/dist/react-portable-text.esm.js:164:22
MyPortableText@webpack-internal:///./src/components/portableText.js:21:16
div
div
div
Container@webpack-internal:///./src/components/container.js:16:18
article
BlogPost@webpack-internal:///./src/components/blog-post.js:30:18
div
Layout@webpack-internal:///./src/components/layout.js:20:18
LayoutContainer@webpack-internal:///./src/containers/layout.js:21:66
BlogPostTemplate@webpack-internal:///./src/templates/blog-post.js:27:14
PageRenderer@webpack-internal:///./.cache/page-renderer.js:23:29
PageQueryStore@webpack-internal:///./.cache/query-result-store.js:39:30
RouteHandler
div
FocusHandlerImpl@webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:359:20
FocusHandler@webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:330:13
RouterImpl@webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:235:20
Location@webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:64:18
Router
ScrollHandler@webpack-internal:///./node_modules/gatsby-react-router-scroll/scroll-handler.js:36:35
RouteUpdates@webpack-internal:///./.cache/navigation.js:294:32
EnsureResources@webpack-internal:///./.cache/ensure-resources.js:22:30
LocationHandler@webpack-internal:///./.cache/root.js:67:29
LocationProvider@webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:84:20
Location@webpack-internal:///./node_modules/@gatsbyjs/reach-router/es/index.js:64:18
Root
dt@webpack-internal:///./node_modules/gatsby-plugin-image/dist/index.browser-44f85d35.js:896:11
StaticQueryStore@webpack-internal:///./.cache/query-result-store.js:158:32
ErrorBoundary@webpack-internal:///./.cache/fast-refresh-overlay/components/error-boundary.js:24:35
DevOverlay@webpack-internal:///./.cache/fast-refresh-overlay/index.js:125:18
RootWrappedWithOverlayAndProvider
App@webpack-internal:///./.cache/app.js:209:68
user Y
Here are the dependencies from my gatsby site:
  "dependencies": {
    "@portabletext/react": "^1.0.2",
    "@sanity/image-url": "^1.0.1",
    "date-fns": "^2.28.0",
    "gatsby": "^4.4.0",
    "gatsby-image": "^3.11.0",
    "gatsby-plugin-image": "2.4.0",
    "gatsby-plugin-postcss": "^5.4.0",
    "gatsby-plugin-react-helmet": "^5.4.0",
    "gatsby-source-sanity": "^7.3.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-gists": "^1.0.0",
    "react-helmet": "^6.1.0"
  }
user Y
Here are the dependencies from my gatsby site:
  "dependencies": {
    "@portabletext/react": "^1.0.2",
    "@sanity/image-url": "^1.0.1",
    "date-fns": "^2.28.0",
    "gatsby": "^4.4.0",
    "gatsby-image": "^3.11.0",
    "gatsby-plugin-image": "2.4.0",
    "gatsby-plugin-postcss": "^5.4.0",
    "gatsby-plugin-react-helmet": "^5.4.0",
    "gatsby-source-sanity": "^7.3.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-gists": "^1.0.0",
    "react-helmet": "^6.1.0"
  }
But given that my pending change is the switch from
@sanity/block-content-to-react
to
@portabletext/react
, isn’t this error related to that single library? Or are you hooking into something Gatsby specific which is different in the new library?
user Z
yes, that works now. Could you add this info to the migration document?
https://github.com/portabletext/react-portabletext/blob/main/MIGRATING.md
user Z
yes, that works now. Could you add this info to the migration document?
https://github.com/portabletext/react-portabletext/blob/main/MIGRATING.md
Will do! Thanks for pointing that out
Will do! Thanks for pointing that out

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?