Complete Guide on React dangerouslySetInnerHTML for 2022
Have you ever noticed that if you have a string with HTML and you try to print it on the screen, it doesn’t quite turn out the way you planned it?
const htmlString = `<h1>I'm a string with HTML!</h1>`;
const App = () => <div>{htmlString}</div>;
Well, that output is just odd looking. Outputs like the one above happens because React JSX is sanitizing the output to prevent any cross-site scripting (XSS).
To make this work, you’re going to have to use React dangerouslySetInnerHTML
.
Let’s dive into when to use this property, and how to use it to your advantage.
What is dangerouslySetInnerHTML
?
dangerouslySetInnerHTML
is a React property that allows you put HTML string values in you render without it being escaped.
dangerouslySetInnerHTML={{ __html: '<h1>I'm a string with HTML!</h1>' }}
This is the equivalent to the JavaScript classic style of using innerHTML
.
document.body.innerHTML = '<h1>Hello World</h1>';
When to use React dangerouslySetInnerHTML
& is it a good idea to use it?
99% of the time you want to avoid using dangerouslySetInnerHTML
because setting HTML from code is very risky. You’re exposing your application to cross-site scripting (XSS). So the question is, when do you use it?
There are occasions when to use dangerouslySetInnerHTML
, such as an API returning HTML string. For example, the WordPress REST api returns HTML in one of its response properties called content
.
If you’re curious to see a sample of a WordPress response object, take a look at this article, “How to make WordPress headless and fetch posts with JavaScript“.
In the context of any CMS using a wysiwyg editor, you want that data of what text is part of a header and what text is part of paragraph. So this is a great use case of when to use React dangerouslySetInnerHTML
.
How to use dangerouslySetInnerHTML
in React
Let’s take the first code example above, and try to make the HTML string render properly by using dangerouslySetInnerHTML
in React
const htmlString = `<h1>I'm a string with HTML!</h1>`;
const App = () => <div dangerouslySetInnerHTML={{ __html: htmlString }} />;
Every HTML element has the React the dangerouslySetInnerHTML
property.
dangerouslySetInnerHTML
must equal an object. And in that object, a property called __html
must equal the string of HTML.
That’s it!
Can you use React dangerouslySetInnerHTML
without the wrapper div?
Yes. You can use dangerouslySetInnerHTML
in all HTML elements.
Here are some examples on how to use it with other HTML elements.
const htmlString = `<h1>I'm a string with HTML!</h1>`;
// Div element
<div dangerouslySetInnerHTML={{ __html: htmlString, }} />
// Span element
<span dangerouslySetInnerHTML={{ __html: htmlString, }} />
// Article element
<article dangerouslySetInnerHTML={{ __html: htmlString, }} />
// H1 element
<h1 dangerouslySetInnerHTML={{ __html: htmlString, }} />
// Head element
<head dangerouslySetInnerHTML={{ __html: htmlString, }} />
A safe React dangerouslySetInnerHTML
alternative
Now, you may be concern of the property name because it has the word dangerous. And you should be alert.
If you’re the only one entering data, you should be at peace that the data wont be dirty.
But if the application or site is accepting data input from multiple people, than you may need to be a tad bit concern.
The goal is still to use the HTML string, but make it safer.
To achieve that, you can use an NPM module called DOMPurify
.
Let’s pretend we have a dirty HTML string from an API.
You can use DOMPurify.sanitize()
to remove any fishy code from a possible dirty string.
import DOMPurify from "dompurify";
const dirty = `I love to do evil <img src="http://unsplash.it/100/100?random" onload="alert('you got hacked');" />`;
const App = () => (
<div
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(dirty)
}}
/>
);
If you’d like to learn about how to use DOMPurify
with React and Node.js, checkout this article, “How to validate and sanitize user input in JavaScript“.
Oh wow, you’ve made it this far! If you enjoyed this article perhaps like or retweet the thread on Twitter:
I like to tweet about React and post helpful code snippets. Follow me there if you would like some too!