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.
exportdefaultfunctionHtmlContent() {
constcontent="<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
JavaScript
exportdefaultfunctionArticle({ body }) {
return (
<article
dangerouslySetInnerHTML={{ __html:body }}
/>
);
}
body should contain valid HTML markup as a string.
Example 2: Conditionally render HTML or fallback
JavaScript
exportdefaultfunctionDescription({ 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
JavaScript
import {useState }from"react";
exportdefaultfunctionPreview() {
const [preview,setPreview]=useState(false);
constcontent="<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:
<divdangerouslySetInnerHTML={content}/>
Why it breaks:
React expects an object with a __html key.
Fix:
CSS
<div
dangerouslySetInnerHTML={{ __html:content }}
/>
Mistake 2: Combining children with dangerouslySetInnerHTML
What you might do:
CSS
<div
dangerouslySetInnerHTML={{ __html:content }}
>
Fallback text
</div>
Why it breaks:
React ignores children when dangerouslySetInnerHTML is used.
Fix: Render conditionally instead.
CSS
{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