hygraph / rich-text

A set of companion packages for Hygraph's Rich Text Field
MIT License
93 stars 18 forks source link

Error while rendering Heading 2 with nested link #51

Closed Aleksander-Drozd closed 2 years ago

Aleksander-Drozd commented 2 years ago

Hi, I noticed that RichText component fails to render content when there is Heading 2 (it probably concerns also other elements) with nested link. The error is

TypeError: Cannot assign to read only property 'children' of object '#<Object>'

GraphCMS content looks like this image

Code that reproduces this this issue below

import { RichText } from '@graphcms/rich-text-react-renderer'

const Component = () => {
  const raw = {
    children: [
      {
        type: 'heading-two',
        children: [
          {
            text: '',
          },
          {
            href: 'https://google.com',
            type: 'link',
            children: [
              {
                text: 'Test heading',
              },
            ],
          },
          {
            text: '',
          },
        ],
      },
    ],
  }

  return <RichText content={raw} />
}
jpedroschmitz commented 2 years ago

Hey @Aleksander-Drozd, thanks for reporting the issue!

I tried to reproduce it, but I wasn't able to do so.

Maybe it's the version of the renderer that you're using.

Here's the link to the CodeSandbox I created to reproduce it.

Aleksander-Drozd commented 2 years ago

Indeed my code does not reproduce the issue. I spent some time looking at it and finally found the root cause. The difference between code above and my production code is source of data - I use Apollo Client to fetch data while in my example data is created by hand. It turns out that Apollo returns read only data and that's what causes the problem. If you make raw variable read only, RichText fails to render content. Assigning data should like this then

// taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
const deepFreeze = (object) => {
  const propNames = Object.getOwnPropertyNames(object)

  for (const name of propNames) {
    const value = object[name]

    if (value && typeof value === 'object') {
      deepFreeze(value)
    }
  }

  return Object.freeze(object)
}

const raw = deepFreeze({
  children: [
    {
      type: 'heading-two',
      children: [
        {
          text: '',
        },
        {
          href: 'https://www.google.com/',
          type: 'link',
          children: [
            {
              text: 'Test heading',
            },
          ],
        },
        {
          text: '',
        },
      ],
    },
  ],
})
jpedroschmitz commented 2 years ago

Got it! I think this error should only happen on development, right?

Anyway, there's nothing that we can do in the library itself in this case. At least I don't have any ideas on how we could handle this, or if it's even possible.

I'll close the issue, but we can reopen it again if needed.

Let me know if you run into any other problems with the library. I'd love to help =D