Skip to content

Next.js 15 Circular Structure Error When passing domNode to another server component #1589

Open

Description

@webplantmedia

I'm not sure if this is a bug, or some problem with my NextJS environment, but in Next 14, I could pass domNode from within the replace() function to other server components, and keep my react customizations more organized. But after upgrading to Next 15, I'm getting the following error:

[ Server ] Error: Converting circular structure to JSON
    --> starting at object with constructor 'Element'
    |     property 'prev' -> object with constructor 'Element'
    --- property 'next' closes the circle

Is this a bug?

  const options: HTMLReactParserOptions = {
    replace(domNode) {
      if (domNode instanceof Element && domNode.attribs) {
        if (domNode.name === 'ul') {
          return <CustomList node={domNode} />;
				}
			}
		}
	}

Activity

  1. changed the title [-]Circular Structure When passing domNode to another server component in Next 15[/-] [+]Circular Structure Error When passing domNode to another server component in Next 15[/+] on Nov 1, 2024
  2. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    Can you provide a reproducible example @webplantmedia? Is this happening on the server-side or client-side? Just curious: if you render with 'use client', does the same error appear?

  3. webplantmedia commented on Nov 1, 2024

    @webplantmedia
    Author

    Happening all on the server side. I read in HTML from an API. I parse the content like so:

      const html = parse(content, options);

    My options are defined similar to the code here:

    const options: HTMLReactParserOptions = {
        replace(domNode) {
          if (domNode instanceof Element && domNode.attribs) {
            if (domNode.name === 'ul') {
              return <CustomList node={domNode} />;
    				}
    			}
    		}
    	}

    Next 14, no error. Next 15, Circular Structure Error.

  4. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    Gotcha I'll try to reproduce this in the example Next.js app in this repository when I have some time today

  5. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    I upgraded the example Next.js app to v15 and I wasn't able to reproduce your error: https://github.com/remarkablemark/html-react-parser/tree/master/examples/nextjs

    Let me know if there's anything I can adjust to reproduce your error

  6. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    My suspicion is that it's coming from this line:

    <CustomList node={domNode} />

    Do you call JSON.stringify on domNode in <CustomList>?

  7. webplantmedia commented on Nov 1, 2024

    @webplantmedia
    Author

    Even this is producing the error for me:

      const options: HTMLReactParserOptions = {
        replace(domNode) {
          function test(node: any) {
            console.log(node);
          }
          test(domNode);
        },
      };
      const html = parse(content, options);
    
      return <>{html}</>;

    Error output:

    Error: Converting circular structure to JSON
        --> starting at object with constructor 'Element'
        |     property 'next' -> object with constructor 'Element'
        --- property 'prev' closes the circle
        at test (rsc://React/Server/webpack-internal:///(rsc)/./components/blocks/parse-blocks.tsx?2:17:25)
        at Object.replace (rsc://React/Server/webpack-internal:///(rsc)/./components/blocks/parse-blocks.tsx?3:19:13)
        at ParseBlocks (rsc://React/Server/webpack-internal:///(rsc)/./components/blocks/parse-blocks.tsx?4:22:79)
        at resolveErrorDev (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:1792:63)
        at processFullStringRow (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2071:17)
        at processFullBinaryRow (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2059:7)
        at progress (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2262:17)
    
    image
  8. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    Do you get the same error if you do this in the example Next.js app? https://github.com/remarkablemark/html-react-parser/tree/master/examples/nextjs

  9. webplantmedia commented on Nov 1, 2024

    @webplantmedia
    Author

    Yes, I do get the same error when in the app directory. No error if in the pages directory. Here is my code in the app directory.

    layout.tsx

    export const metadata = {
      title: 'Next.js',
      description: 'Generated by Next.js',
    }
    
    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode
    }) {
      return (
        <html lang="en">
          <body>{children}</body>
        </html>
      )
    }

    page.tsx

    import parse, { Element } from 'html-react-parser';
    
    type Props = {
      params: { slug: string };
    };
    
    export default async function Page({ params }: Props) {
      return (
        <main>
          <h1 className="title">
            {parse(
              `
                Welcome to <a href="https://nextjs.org">Next.js</a>
                and HTMLReactParser!
              `,
              {
                replace(domNode) {
                  function test(node: any) {
                    console.log(node);
                  }
                  test(domNode);
    
                  if (domNode instanceof Element && domNode.name === 'a') {
                    return (
                      <a href="https://nextjs.org" rel="noopener noreferrer">
                        Next.js
                      </a>
                    );
                  }
                },
              }
            )}
          </h1>
        </main>
      );
    }

    Error:

    Error: Converting circular structure to JSON
        --> starting at object with constructor 'Text'
        |     property 'next' -> object with constructor 'Element'
        --- property 'prev' closes the circle
        at test (rsc://React/Server/webpack-internal:///(rsc)/./app/page.tsx?0:20:33)
        at Object.replace (rsc://React/Server/webpack-internal:///(rsc)/./app/page.tsx?1:22:21)
        at Page (rsc://React/Server/webpack-internal:///(rsc)/./app/page.tsx?2:14:84)
        at resolveErrorDev (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:1792:63)
        at processFullStringRow (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2071:17)
        at processFullBinaryRow (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2059:7)
        at progress (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/compiled/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js:2262:17)
    
    image

    package.json

    {
      "scripts": {
        "dev": "next dev",
        "build": "next build",
        "start": "next start"
      },
      "dependencies": {
        "html-react-parser": "^5.1.18",
        "next": "^15.0.2",
        "react": "^18.3.1",
        "react-dom": "^18.3.1"
      },
      "devDependencies": {
        "@types/node": "22.8.6",
        "@types/react": "18.3.12",
        "typescript": "5.6.3"
      }
    }
  10. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    Can you fork and create a branch with these changes? @webplantmedia

  11. webplantmedia commented on Nov 1, 2024

    @webplantmedia
    Author

    https://github.com/webplantmedia/html-react-parser

    I just pushed a commit with the code. Thanks so much for looking into it! I have based a very big next js project in using this react parser. I'm hoping there is an easy fix to this without having to refactor lots of code.

    https://github.com/webplantmedia/html-react-parser/tree/master/examples/nextjs

  12. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    Thanks! I'll take a look later today @webplantmedia

  13. webplantmedia commented on Nov 1, 2024

    @webplantmedia
    Author

    Any insight on the nature of this error? Is it some new code procedure introduced in next js 15? If it is permanent, would I need to drop support of this parser if I need to stick with Next JS? Thank you again. I've been stuck on this for two days.

  14. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    @webplantmedia this is happening because Next.js tries to render the data as JSON in a <script> tag:

    Screenshot 2024-11-01 at 4 53 07 PM

    There are 3 solutions:

    1. Add 'use client' to the top of the file <CustomList> but you will lose server-side rendering
    2. Instead of passing domNode to the function, pass the specific keys and values
    3. Remove circular references from domNode: https://stackoverflow.com/questions/66091604/how-do-i-remove-all-circular-references-from-an-object-in-javascript
  15. webplantmedia commented on Nov 1, 2024

    @webplantmedia
    Author

    Sigh. I really needed to be able to loop inside other components. And keep it as a server component. Do you see this being a permanent move by nextjs 15 on how they handle complex objects?

    I really appreciate your insight. Thanks so much.

  16. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    @webplantmedia I'm not sure, but I think it's worth creating an issue or discussion on Next.js to confirm. For now, I think 3 could resolve the issue for you, but there may be a chance that it breaks your project.

  17. changed the title [-]Circular Structure Error When passing domNode to another server component in Next 15[/-] [+]Next.js 15 Circular Structure Error When passing `domNode` to another server component[/+] on Nov 1, 2024
  18. webplantmedia commented on Nov 1, 2024

    @webplantmedia
    Author

    I did!

    vercel/next.js#72189

    I'm assuming if I remove circular reference, it would break domToReact(node?.children as DOMNode[], options) in other components. Let me know if that's not the case. Also, seems like a lot of extra recursion too for large html content.

    But I can't even console log domNode if I want to debug in a server component.

    Two other html parsers I looked into also have circular referencing.

    Sigh.

  19. remarkablemark commented on Nov 1, 2024

    @remarkablemark
    Owner

    @webplantmedia yes there's a possibility that if you remove circular reference that it would break domToReact(). This library is built using html-dom-parser, which uses htmlparser2 under the hood. That's where the circular references are coming from.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

questionFurther information is requested

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions