How to Render HTML in React
What you’ll build or solve
You’ll render HTML markup from a string inside a React component.
When this approach works best
Rendering HTML works best when you need to:
Learn React on Mimo
- Display rich text stored in a CMS or database.
- Render formatted content returned from an API.
- Inject trusted HTML snippets into a component.
Avoid rendering raw user input directly without first reviewing or sanitizing it. Rendering unsafe HTML can expose your app to security risks.
Prerequisites
- A React app set up
- Basic JSX knowledge
Step-by-step instructions
1) Render HTML with dangerouslySetInnerHTML
By default, JSX escapes HTML strings for security. If you pass a string that contains tags, React renders it as plain text.
To render actual HTML markup from a string, use the dangerouslySetInnerHTML prop.
JSX
export default function HtmlContent() {
const content = "<strong>Hello</strong> world";
return (
<div
dangerouslySetInnerHTML={{ __html: content }}
/>
);
}
Key points
- The prop name must be
dangerouslySetInnerHTML. - It expects an object with a
__htmlproperty. - The value of
__htmlmust be a string.
What to look for
- The object shape must be exactly
{ __html: content }. - You cannot use children and
dangerouslySetInnerHTMLon the same element. - The word “dangerous” is intentional. React will not escape the HTML for you.
Examples you can copy
Example 1: Render CMS article content
JSX
export default function Article({ body }) {
return (
<article
dangerouslySetInnerHTML={{ __html: body }}
/>
);
}
body should contain valid HTML markup as a string.
Example 2: Conditionally render HTML or fallback
JSX
export default function Description({ html }) {
if (!html) {
return <p>No description available.</p>;
}
return (
<div
dangerouslySetInnerHTML={{ __html: html }}
/>
);
}
Use normal conditional rendering to decide whether to inject HTML.
Example 3: Toggle between raw text and rendered HTML
JSX
import { useState } from "react";
export default function Preview() {
const [preview, setPreview] = useState(false);
const content = "<em>Preview content</em>";
return (
<div>
<button
onClick={() => setPreview((p) => !p)}
>
Toggle preview
</button>
{preview ? (
<div
dangerouslySetInnerHTML={{ __html: content }}
/>
) : (
<div>{content}</div>
)}
</div>
);
}
When preview is true, the markup renders as HTML. Otherwise, it displays as plain text.
Common mistakes and how to fix them
Mistake 1: Passing a string instead of an object
What you might do:
JSX
<div dangerouslySetInnerHTML={content} />
Why it breaks:
React expects an object with a __html key.
Fix:
JSX
<div
dangerouslySetInnerHTML={{ __html: content }}
/>
Mistake 2: Combining children with dangerouslySetInnerHTML
What you might do:
JSX
<div
dangerouslySetInnerHTML={{ __html: content }}
>
Fallback text
</div>
Why it breaks:
React ignores children when dangerouslySetInnerHTML is used.
Fix: Render conditionally instead.
JSX
{content ? (
<div
dangerouslySetInnerHTML={{ __html: content }}
/>
) : (
<p>No content</p>
)}
Troubleshooting
- If HTML appears as literal text with angle brackets, confirm you are using
dangerouslySetInnerHTMLinstead of{content}. - If nothing renders, check that the string is not
nullorundefined. - If React throws a warning about invalid props, confirm the object format is
{ __html: value }. - If your security scanner flags an issue, review how the HTML string is created and whether it needs sanitization before rendering.
Quick recap
- JSX escapes HTML strings by default.
- Use
dangerouslySetInnerHTMLto render real HTML. - Pass an object with a
__htmlproperty. - Do not combine children with
dangerouslySetInnerHTML. - Treat injected HTML as potentially unsafe and handle it carefully.
Join 35M+ people learning for free on Mimo
4.8 out of 5 across 1M+ reviews
Check us out on Apple AppStore, Google Play Store, and Trustpilot