question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[devalue: Cannot stringify a function] Can't get dynamic component tree to SSR properly

See original GitHub issue

Hey there,

First of all, I’m sorry that I have to open this issue here, I’m quite new to SSR and it’s probably possible to find my answers somewhere somehow, though I’m already pretty stressed out as I don’t understand what’s going wrong and that I don’t understand it 🤯😅

So I’m trying to render the following JSON

{
  "title": "CanRau.com Homepage",
  "content": [
    {
      "component": "section",
      "props": {
        "className": "bg-nord1 mx-auto pt-2 text-nord5",
        "key": "indexSection"
      },
      "children": [
        {
          "component": "Hero",             <-- Here lies the problem
          "props": {
            "className": "bg-primary",
            "key": "indexHero"
          }
        },
        {
          "component": "h1",
          "props": {
            "className": "bg-red",
            "key": "indexH1"
          },
          "children": "H1"
        }
      ]
    }
  ]
}

Everything works fine until I introduce custom components like "component": "Hero" which will be replaced with a, well, custom component.

This is the code to dynamically render the tree

const renderDynamicComponents = (tree, components) =>
  tree.map((item, index) => {
    if (!item.component) return item;

    const Comp = item.component;
    const props = item.props ?? {};

    if (!props?.key) {
      throw new Error(
        `Component is missing a unique 'key' for ${console.log(
          JSON.stringify({ index, component: Comp })
        )}`
      );
    }

    if (item.children !== undefined) {
      if (typeof item.children === "string") {
        props.children = item.children;
      } else if (Array.isArray(item.children)) {
        props.children = renderDynamicComponents(item.children, components);
      }
    }

    if (components?.[Comp] !== undefined) {
      return createElement(components[Comp], props);
    }

    return createElement(Comp, props);
  });

which sadly throws

Error: Cannot stringify a function
    at walk ([..]/node_modules/devalue/dist/devalue.umd.js:29:20)

I thought I figured a solution by only running renderDynamicComponents on the client, then I realized that that’s defeating the purpose of SSR tho 🤦🏻‍♂️

My problem

I don’t fully understand why this is happening, when I

// ..
props.children = renderDynamicComponents(item.children, components);
console.log(props.children);
// ..

I get:

{
    '$$typeof': Symbol(react.element),
    type: [Function: HeroComponent],          <--- this is most probably the issue, right?
    key: 'indexHero',
    ref: null,
    props: { className: 'bg-primary' },
    _owner: null,
    _store: {}
  },
  {
    '$$typeof': Symbol(react.element),
    type: 'h1',
    key: 'indexH1',
    ref: null,
    props: { className: 'bg-red', children: 'H1' },
    _owner: null,
    _store: {}
  }

Thought I’m smart again, for a split second, trying to HeroComponent.prototype.toString = () => "hero";, though nothing 🥲

What can I do about this, what options do I have? The example JSON will be coming from my CMS, I thought about using MDX instead though I’d highly prefer less abstraction, as it’s machine handled and edited using the CMS’s UI anyway.

Please help 🥺

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:13 (13 by maintainers)

github_iconTop GitHub Comments

2reactions
brilloutcommented, Aug 5, 2021

Thanks 😃.

Have fun building 😉.

2reactions
brilloutcommented, Aug 5, 2021

Let me have a look

Read more comments on GitHub >

github_iconTop Results From Across the Web

Nuxt: All pages show a warning "Cannot stringify a function ...
it passes state from asyncData, data, vuex store state from server to client. The package that throws this error is @nuxt/devalue used by...
Read more >
error NuxtServerError: Cannot stringify a function #4026 - GitHub
Right now the solution is to modify "devalue" package and comment out the error. Future version of nuxt will have a fork of...
Read more >
@sheerun/next - npm Package Health Analysis | Snyk
The default behaviour for the <Link> component is to push a new url into the stack. You can use the replace prop to...
Read more >
Connect your content to SvelteKit - Sanity.io
In this guide, you will add the necessary code to a SvelteKit starter to pull in your content from your Sanity Content Lake....
Read more >
Routing • Docs • SvelteKit
A +page.svelte component defines a page of your app. By default, pages are rendered both on the server (SSR) for the initial request...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found