We have a database containing HTML code and we are displaying that on a web page using React, but it needs to be parsed.

I initially used html-react-parser but after a code review was asked to use dangerouslySetInnerHtml instead because it doesn't have any dependencies.

I wasn't able to articulate any advantages of using html-react-parser other than it doesn't use dangerouslySetInnerHtml, but is that an advantage and if so why? Does it somehow avoid the dangers or are they just hidden?

Many thanks,

Katie

1

There are 1 best solutions below

4
On BEST ANSWER

I've recently been studying this issue for a Headless CMS project I'm working on. From what I understand:

dangerouslySetInnerHtml creates DOM elements outside of ReactDOM.Render() method, so it's not dynamically maintained by the React library. This basically defeats the purpose of using React in the first place (displaying and maintaining virtual DOM).

More concerning, though, is that it's vulnerable to Cross-Site Scripting (XSS) attacks, which is where it gets its name. These are a very common form of attack on the web. You can read about that here: https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

If you want the app to be less prone to attacks, you'll have to use a sanitization library like DOMPurify for dangerouslySetInnerHtml, so you're likely to have another dependency either way. Once you compile the app for production (npm build) the minimization process makes the codebase extremely compact, and you can do some optimization beforehand with techniques like code-splitting, which makes each section of your page load only if requested, instead of all at once: https://reactjs.org/docs/code-splitting.html

I wouldn't worry too much about a few dependencies, personally - they're a fact of life on the modern web. I've been leaning towards using html-react-parser, but I caveat that by saying I have not investigated whether it reduces XSS vulnerability. However, even if both are vulnerable to XSS attacks, at least html-react-parser introduces the elements through ReactDOM.render() so they don't make the DOM all catty-wompus - that sounds like a recipe for disaster down the road.