React.Js: Set Innerhtml VS Dangerouslysetinnerhtml

React.js: Set innerHTML vs dangerouslySetInnerHTML

Yes there is a difference!

The immediate effect of using innerHTML versus dangerouslySetInnerHTML is identical -- the DOM node will update with the injected HTML.

However, behind the scenes when you use dangerouslySetInnerHTML it lets React know that the HTML inside of that component is not something it cares about.

Because React uses a virtual DOM, when it goes to compare the diff against the actual DOM, it can straight up bypass checking the children of that node because it knows the HTML is coming from another source. So there's performance gains.

More importantly, if you simply use innerHTML, React has no way to know the DOM node has been modified. The next time the render function is called, React will overwrite the content that was manually injected with what it thinks the correct state of that DOM node should be.

Your solution to use componentDidUpdate to always ensure the content is in sync I believe would work but there might be a flash during each render.

Safe alternative to dangerouslySetInnerHTML

If XSS is your primary concern, you can use DOMPurify to sanitize your HTML before inserting it in the DOM via dangerouslySetInnerHTML. It's just 10K minified. And it works in Node too.

Alternative to dangerouslySetInnerHTML

Perhaps these parsers can fulfill ur need

html-to-react

html-react-parser

What are the pros and cons of using an HTML parsing package like html-react-parser vs dangerouslySetInnerHtml in React

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.

set innerHtml from a sanitized html is still dangerous?

But I sanitized my html with dompurify. Does this completely protect me from XSS attacks?

Likely yes, but it's not 100% guaranteed. If DOMPurify doesn't have bugs that will let XSS through, setting innerHTML or dangerouslySetInnerHTML with its results will be safe. DOMPurify is open-source and relatively popular, so if it did have such vulnerabilities, they would probably have been seen by now.

But, like with everything humans do, mistakes and coincidences that result in vulnerabilities not being seen are still possible.

Add Icon in dangerously set Inner html in React

You can simply put an icon on each item:

Assume that your keyArray is something like this:

const keyArray = ["World", "Americas", "South", "America"];

Now, you can use map function to add an icon for each item:

const result = data.map((item, i) => (
<div key={i}>
<ArrowRightIcon />
<span>{item}</span>
</div>
));

the result

Now, the result is ready to use, with a parent div and flex style, the final result will be produced:

<div style={{ display: "flex" }}>{result}</div>

final result

How to run a loop inside a jsx string set using dangerouslySetInnerHTML

Since you want it to be a string, you must return a string inside the map(), not a html element, change the stringJsx to something like:

const stringJsx = (`
<ol>
${
items.map((item, index) => {
return `<li key=${index}>this is a nice item : ${item.name}</li>`;
}).join('')
}
</ol>
`);

Btw: consider using join('') after the map so there won't be any ,'s in between the <li>'s

Full snippet using the above code:

class Example extends React.Component {    
render() {

const items = [{name: 'nice'},{ name: 'bice'}, {name: 'tice'}];
const stringJsx = (`
<ol>
${
items.map((item, index) => {
return `<li key=${index}>this is a nice item : ${item.name}</li>`;
}).join('')
}
</ol>
`);

return (
<React.Fragment>
<h1 id='nice'> this is a nice h1 tag</h1>
<div dangerouslySetInnerHTML={{ __html: stringJsx }} />
</React.Fragment>
)
}
}

ReactDOM.render(<Example />, document.body);
:root{
--bg-clr-1: #E7F8F8;
--card-clr-red: #F03E3E;
--card-clr-violet: #7950F2;
--card-clr-green: #12B886;
--text-clr: #333;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>


Related Topics



Leave a reply



Submit