Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →“Convert a React string to HTML” can mean three different jobs. If you have a React element or component tree and need an HTML string, use renderToStaticMarkup for non-interactive output or renderToString (and hydration) for an interactive app. If you already have an HTML string, you are inserting markup, not converting React; use dangerouslySetInnerHTML only with trusted, sanitized content. If you have plain text, render it as a normal React child so React escapes it.
The right API depends on the input, whether the result must hydrate, and whether rendering happens on a server or in a browser.
Choose the operation before writing code
| What you have | What you need | Use | Main limitation |
|---|---|---|---|
| A React node, element, or component tree | Static HTML text for an email, file, or API response | renderToStaticMarkup |
The result cannot be hydrated. |
| A React tree for an interactive page | Initial server HTML that the browser will activate | renderToString plus hydrateRoot |
It returns immediately; it does not stream or wait for data. |
| A React tree on a server that should arrive progressively | Streamed HTML | renderToPipeableStream in Node.js or renderToReadableStream in Web Streams runtimes |
The API is runtime-specific. |
| A React tree in browser code | The generated DOM HTML | Render into a temporary element, flush, then read innerHTML |
Do not ship server-rendering code to the client just to serialize markup. |
| An existing HTML string | Markup displayed by React | dangerouslySetInnerHTML |
Untrusted input can create an XSS vulnerability. |
| Plain text | Safe text inside an element | Use it as a normal React child | It remains text; tags in the string are not interpreted. |
These distinctions match React’s server-rendering and common-component guidance: renderToStaticMarkup produces non-interactive markup, while renderToString is for the initial HTML of an app that will hydrate.
Convert a React component to a static HTML string
For a non-interactive result, import renderToStaticMarkup from react-dom/server. It returns a string containing the rendered tree and is suitable for static page generation or content such as emails.
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
function Invoice({ number, total }) {
return (
<main>
<h1>Invoice {number}</h1>
<p>Total: ${total}</p>
</main>
);
}
const html = renderToStaticMarkup(
<Invoice number="A-1042" total="125.00" />
);
console.log(html);
The returned value is ordinary JavaScript text. You can write it to a file, place it in an email body, or send it in an HTTP response. Because static markup has no React hydration data, do not call hydrateRoot on this output; if you need interactivity, use the next approach instead.
Render HTML that will become an interactive React app
Use renderToString when the server must send initial markup and the browser will attach React event handlers afterward. The server output is only the first render; the client must hydrate the same tree.
// server.mjs
import React from 'react';
import { renderToString } from 'react-dom/server';
import { App } from './App.js';
const html = renderToString(<App />);
// Insert html into your document response.
// browser entry
import { hydrateRoot } from 'react-dom/client';
import { App } from './App.js';
hydrateRoot(document.getElementById('root'), <App />);
renderToString returns immediately. It does not stream output or wait for suspended data; when a child suspends, React renders the nearest Suspense fallback in this mode. If progressive delivery or data-aware rendering is required, use the streaming or prerender APIs described below.
Keep server and client markup identical
- Render the same component tree and initial props on both sides.
- Avoid reading browser-only values during the server render; defer them until the client is hydrated.
- Make sure locale, timezone, and random values do not produce different text between renders.
- Place the same root element in the document that the client passes to
hydrateRoot.
Stream or wait for data on the server
For progressive server output, React provides renderToPipeableStream for Node.js and renderToReadableStream for Web Streams runtimes. These APIs let the response begin while parts of the tree are still resolving, subject to the Suspense boundaries in your app.
If the requirement is static output that waits for data rather than streaming chunks as they become available, use React’s prerender API in Web Streams environments and the documented Node.js counterpart. Choose the API that matches your server runtime; the current server API index is maintained at React’s Server React DOM APIs reference, and the static API is documented at prerender.
Rank #2
Convert a React tree to HTML in the browser
React does not recommend importing the server-rendering package into client code merely to call renderToString. Instead, create a temporary DOM element, render into it with createRoot, synchronously flush the update, and read innerHTML.
import React from 'react';
import { createRoot } from 'react-dom/client';
import { flushSync } from 'react-dom';
export function reactToHtml(node) {
const container = document.createElement('div');
const root = createRoot(container);
flushSync(() => {
root.render(node);
});
const html = container.innerHTML;
root.unmount();
return html;
}
const html = reactToHtml(
<article>
<h2>Rendered in the browser</h2>
<p>This is now a string of DOM markup.</p>
</article>
);
console.log(html);
flushSync is important here: without a synchronous flush, reading innerHTML immediately after root.render can occur before the DOM update is committed. This method serializes the DOM produced by the browser, so browser-only behavior and effects should be treated separately from the initial render.
When the “React string” is actually plain text
A JavaScript string used as a React child is text, not HTML. React escapes characters such as < and & when it renders the child.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesfunction Message({ text }) {
return <p>{text}</p>;
}
// The following is displayed literally, not interpreted as a tag:
<Message text="<strong>Not bold</strong>" />
This is the safe default for user-entered content. Do not parse a text string as markup unless you have a specific, trusted-content requirement and a sanitizer appropriate to your input.
Insert an existing HTML string into a React component
If your input is already HTML, the operation is insertion rather than conversion. React’s escape hatch is dangerouslySetInnerHTML:
Rank #3
function ArticleBody({ sanitizedHtml }) {
const markup = { __html: sanitizedHtml };
return <div dangerouslySetInnerHTML={markup} />;
}
Only pass content that is trusted and sanitized. React’s common-components documentation warns that untrusted HTML, including user-provided content, can introduce an XSS vulnerability; see the React common-components reference. Sanitizing after insertion is too late, because the browser may already have parsed dangerous elements or attributes. Prefer ordinary React children when the value should remain text.
Trusted Types and sanitization
React supports a TrustedHTML value when your application enforces Trusted Types, but the policy that creates that value must still ensure the source is trusted and sanitized. Trusted Types do not make arbitrary user HTML safe by themselves.
Common errors and fixes
“Objects are not valid as a React child”
You may be passing a component object or an unrendered data structure where React expects a node. Pass an element such as <Card /> to the rendering API, or map your data to elements first.
The result is empty or incomplete in browser code
Read innerHTML only after the render has committed. The browser technique above uses flushSync; also ensure the component does not depend on asynchronous work that has not completed.
Hydration warnings appear
The server string and the client tree differ. Check serialized props, locale and timezone settings, random IDs, browser-only branches, and the exact root element. Render deterministic initial content, then update client-only values after hydration.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Suspense content is not present in renderToString
This API does not wait for suspended data and emits the nearest fallback. Use a streaming API for progressive Suspense handling or a prerender API when the output must wait for data.
Recommended Free Tools
HTML tags show as text
That is expected when a string is supplied as a normal child. Use React elements for structure. If the value is an existing HTML document, use sanitized dangerouslySetInnerHTML only when the security requirements are met.
Scripts or event handlers do not work in static output
renderToStaticMarkup creates markup; it does not attach React event handlers and its output cannot be hydrated. Use the server-plus-hydration workflow for an interactive app.
Performance, output, and security considerations
- Use static rendering for one-way output such as emails and prebuilt documents; it avoids hydration work because it is deliberately non-interactive.
- Use
renderToStringonly when the browser will hydrate the result. Sending interactive markup without hydrating it adds bytes without enabling behavior. - Streaming can improve time-to-first-byte for large trees, while prerendering is appropriate when complete data is required before sending output.
- In-browser serialization creates and mounts a real DOM tree, so remove the temporary root with
unmountafter reading the markup. - Never treat HTML escaping and HTML sanitization as interchangeable. Escaping keeps a value as text; sanitization removes unsafe markup from content you intentionally render as HTML.
- Test the serialized output for required attributes and text, and test the hydrated app separately for event handlers and client behavior.
Or skip the browser setup
If your actual goal is to capture the rendered page as an image or PDF after it has become HTML, ScreenshotNeo can do the browser work with one request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
See the ScreenshotNeo API documentation for all options. A direct call looks like this:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The Free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.
Best Value
FAQ
Can static markup be hydrated later?
No. Use renderToString when the output must become an interactive React app.
Should I use innerHTML on a React element?
No. Render the element into a temporary root, flush it, and read that root’s innerHTML.
Is dangerouslySetInnerHTML a converter?
No. It inserts an existing HTML string, and it requires trusted, sanitized content.
Free tools Windows power users keep installed
One-click scans. No signup required.
Frequently Asked Questions
Can static markup be hydrated later?
No. Use renderToString when the output must become an interactive React app.
Should I use innerHTML on a React element?
No. Render the element into a temporary root, flush it, and read that root’s innerHTML.
Is dangerouslySetInnerHTML a converter?
No. It inserts an existing HTML string, and it requires trusted, sanitized content.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →




