kaicataldo / eleventy-plugin-react

A plugin that allows you to use React as a templating language for Eleventy
MIT License
38 stars 4 forks source link

Circular JSON issue when using `withHydration` #34

Open mraerino opened 2 years ago

mraerino commented 2 years ago

Eleventy Version: 0.12.1 or 1.0

When using withHydration on a layout component, I get this error:

Problem writing Eleventy templates: (more in DEBUG output)
> Having trouble writing template: _site/posts/hello/index.html

`TemplateWriterWriteError` was thrown
> Converting circular structure to JSON
    --> starting at object with constructor 'EleventyExtensionMap'
    |     property '_engineManager' -> object with constructor 'TemplateEngineManager'
    |     property 'engineCache' -> object with constructor 'Object'
    |     property 'jsx' -> object with constructor 'CustomEngine'
    --- property '_extensionMap' closes the circle

`TypeError` was thrown:
    TypeError: Converting circular structure to JSON
        --> starting at object with constructor 'EleventyExtensionMap'
        |     property '_engineManager' -> object with constructor 'TemplateEngineManager'
        |     property 'engineCache' -> object with constructor 'Object'
        |     property 'jsx' -> object with constructor 'CustomEngine'
        --- property '_extensionMap' closes the circle
        at JSON.stringify (<anonymous>)
        at HydratedComponent (/Users/christine/code/kalkspace-relaunch/node_modules/eleventy-plugin-react/lib/components/withHydration.js:33:40)
        at processChild (/Users/christine/code/kalkspace-relaunch/node_modules/react-dom/cjs/react-dom-server.node.development.js:3353:14)
        at resolve (/Users/christine/code/kalkspace-relaunch/node_modules/react-dom/cjs/react-dom-server.node.development.js:3270:5)
        at ReactDOMServerRenderer.render (/Users/christine/code/kalkspace-relaunch/node_modules/react-dom/cjs/react-dom-server.node.development.js:3753:22)
        at ReactDOMServerRenderer.read (/Users/christine/code/kalkspace-relaunch/node_modules/react-dom/cjs/react-dom-server.node.development.js:3690:29)
        at Object.renderToString (/Users/christine/code/kalkspace-relaunch/node_modules/react-dom/cjs/react-dom-server.node.development.js:4298:27)
        at /Users/christine/code/kalkspace-relaunch/node_modules/eleventy-plugin-react/lib/plugin.js:83:33
        at TemplateLayout.render (/Users/christine/code/kalkspace-relaunch/node_modules/@11ty/eleventy/src/TemplateLayout.js:152:31)
        at async Template.renderPageEntry (/Users/christine/code/kalkspace-relaunch/node_modules/@11ty/eleventy/src/Template.js:603:17)

I was able to track this to the collections prop that is passed to all layout components. It seems to include circular references. Consider removing the circular references before serializing the state for hydrated components.

kaicataldo commented 2 years ago

I think this is due to a change introduced in v1.0. Should be fixed when we update the plugin to support the new API.

mraerino commented 2 years ago

i think i also saw it on 0.12.1, but fine if it's fixed for 1.0 only

kaicataldo commented 2 years ago

Ah okay, in that case we'll probably just want to have a better error message here and maybe have some escape hatch that allows you to filter out data from other plugins. Only interactive components should have serialized props, so at some point it's up to the user to work around the limitations introduced by that pattern (i.e. props must only contain serializable properties).

The intended use-case here is for a mostly static site that has some interactivity sprinkled in, rather than a server-side rendered full-page progressive web app. If that's the end goal, I think some other tools might be better suited towards those goals.

As a workaround, a user could have a top-level static Page component that only passes through serializable data to a hydrated App component that renders the entire body of the page. I think this would be preferable anyway, since including all of Eleventy's data as serialized props is a lot of bloat on the page.

mraerino commented 2 years ago

that makes perfect sense, thanks for looking into it!

i'd appreciate some way to filter props for hydration