Skip to content

Provide a way to pass context to renderToStaticMarkup on the client #14292

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

Closed
gaearon opened this issue Nov 20, 2018 · 4 comments
Closed

Provide a way to pass context to renderToStaticMarkup on the client #14292

gaearon opened this issue Nov 20, 2018 · 4 comments
Labels

Comments

@gaearon
Copy link
Collaborator

gaearon commented Nov 20, 2018

See #14287 (comment) and #14182 (comment). This accidentally worked for a few releases but was a bug. However we might want to consider actually supporting this with an opt-in API.

@gaearon
Copy link
Collaborator Author

gaearon commented Mar 29, 2022

Generally, using SSR methods on the client is discouraged. Instead, it's better to render into a DOM node and then read innerHTML from it, for example. This also solves the context issue.

@gaearon gaearon closed this as completed Mar 29, 2022
@nomcopter
Copy link

@gaearon what are the advantages of that approach? Does the browser provide some normalization or other advantage?

@gaearon
Copy link
Collaborator Author

gaearon commented Mar 30, 2022

It's unfortunate to bundle a whole server renderer on the page just to produce HTML since you can already produce HTML just with React DOM. Additionally, if you do it in your component, you still have the context etc, which is what the original complaint was about.

@sneko
Copy link

sneko commented Feb 19, 2025

@gaearon using renderToStaticMarkup is pretty easy but I get the point of not bundling backend stuff. I tried the following function but unfortunately the container.innerHTML is always empty probably because the render() method is async (I deduce that since when looking at my browser console I can see the container element having content then).

What would be the best way to keep it simple to wait for the render? Should I use a MutationObserver or is there something simpler?

function frontendRenderToStaticMarkup(component: JSX.Element): string {
  const container = document.createElement('div');
  const root = createRoot(container);
  root.render(component);

  console.log(container.innerHTML);
  console.log(container.outerHTML);

  const html = container.innerHTML;

  console.log(container);
  console.log(html);
  console.log(root);

  // root.unmount();

  return html;
}

Thank you,

EDIT: note in my case I don't want it to be displayed to the user, that's why I try to do things isolated. Maybe a solution would be to mount my component into the page while being display: none but it looks hacky. Also, it needs some processing on variables so it would be kind of useless calculation if hidden. Maybe I could set a rendering condition, but I guess I would need to use useEffect() to know when I can really consider the DOM to be updated.

In my case I just wanted to reuse the JSX templating with some context like translations to generate HTML to be put into the clipboard.

EDIT2: I ended with a boolean state on the parent component to display the child, and within the child a useEffect getting the HTML from the top element thanks to a reference (the top element is hidden by default). Once done I call a callback so the parent can remove it from the DOM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants