Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Circular Structure Error When passing complex objects with circular reference to another server component or function in Next 15 #72189

Open
webplantmedia opened this issue Nov 1, 2024 · 7 comments
Labels
bug Issue was opened via the bug report template.

Comments

@webplantmedia
Copy link

webplantmedia commented Nov 1, 2024

Link to the code that reproduces this issue

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

To Reproduce

I can't seem to pass complex objects to other server components or functions without getting a circular structure error. Specifically, I'm using html-react-parser and manipulating certain elements to render custom jsx. It worked fine and without error in nextjs 14.

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"
  }
}

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

Current vs. Expected behavior

The bug is not being able to pass a complex object to different server functions or server components. It was not an issue in Next 14.

Provide environment information

chrisb@Chriss-MacBook-Pro nextjs % npm run info

> info
> next info

warning package.json: No license field

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.6.0: Mon Jul 29 21:14:30 PDT 2024; root:xnu-10063.141.2~1/RELEASE_ARM64_T6000
  Available memory (MB): 16384
  Available CPU cores: 10
Binaries:
  Node: 20.15.1
  npm: 10.7.0
  Yarn: 1.22.22
  pnpm: N/A
Relevant Packages:
  next: 15.0.2 // Latest available version is detected (15.0.2).
  eslint-config-next: N/A
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.6.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not sure

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

I tested with next 15.0.2

@icyJoseph
Copy link
Contributor

This looks like a React issue to be honest, but I am still collecting info.

Discussion answer: #72225 (comment)

@webplantmedia
Copy link
Author

Thanks so much for looking into it. Do you think it is safe to assume that this bug will be worked out, and that it is acceptable coding practice to pass complex objects with circular reference as component parameters in nextjs 15?

@icyJoseph
Copy link
Contributor

That I don't know. I think we can try to make a smaller reproduction demo, without any additional libraries etc, and try to ping Seb Markbåge, to get their opinion.

Assuming this problem is caused because, we try to serialize data, to display in the DevTools, then there should be some kind of way out.

From MDN:

To serialize circular references, you can use a library that supports them (e.g. cycle.js by Douglas Crockford) or implement a solution yourself, which will require finding and replacing (or removing) the cyclic references by serializable values.

@icyJoseph
Copy link
Contributor

icyJoseph commented Nov 5, 2024

Here is a minimal Stackblitz fork: https://stackblitz.com/edit/nextjs-wwb9nh?file=app%2Fpage.tsx,package.json

function Child(props: unknown) {
  console.log(props);
  return <div></div>;
}

export default function Home() {
  const props: Record<string, unknown> = {};

  props.props = props;

  return <Child {...props} />;
}

Specifically, console.log on the circular object, is the issue. Passing the circular object as props, causes the issue... The logging is not necessarily the issue.

In Next 14, we'd log:

<ref *1> { props: [Circular *1] }

But in Next 15, I guess with a bumped React family version, we error out. Maybe upon a serialising error, we should try to fallback on old behaviour? Again, this looks like something to fix upstream on React itself.

@sebmarkbage sorry to ping ya, could you confirm this? Looks like an odd minor issue ~

@webplantmedia
Copy link
Author

The error also appears if you pass a complex object through a component (as opposed to just a function). Component parameters get stringified also, which triggers the error.

@webplantmedia

This comment has been minimized.

@icyJoseph

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests

2 participants