React.js: Set innerHTML vs dangerouslySetInnerHTML

410,955

Solution 1

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.

Solution 2

You can bind to dom directly

<div dangerouslySetInnerHTML={{__html: '<p>First &middot; Second</p>'}}></div>

Solution 3

According to Dangerously Set innerHTML,

Improper use of the innerHTML can open you up to a cross-site scripting (XSS) attack. Sanitizing user input for display is notoriously error-prone, and failure to properly sanitize is one of the leading causes of web vulnerabilities on the internet.

Our design philosophy is that it should be "easy" to make things safe, and developers should explicitly state their intent when performing “unsafe” operations. The prop name dangerouslySetInnerHTML is intentionally chosen to be frightening, and the prop value (an object instead of a string) can be used to indicate sanitized data.

After fully understanding the security ramifications and properly sanitizing the data, create a new object containing only the key __html and your sanitized data as the value. Here is an example using the JSX syntax:

function createMarkup() {
    return {
       __html: 'First &middot; Second'    };
 }; 

<div dangerouslySetInnerHTML={createMarkup()} /> 

Read more about it using below link:

documentation: React DOM Elements - dangerouslySetInnerHTML.

Solution 4

Based on (dangerouslySetInnerHTML).

It's a prop that does exactly what you want. However they name it to convey that it should be use with caution

Solution 5

Yes there is a difference b/w the two: dangerouslySetInnerHTML: React diffing algorithm (https://reactjs.org/docs/reconciliation.html) is designed to ignore the HTML nodes modified under this attribute thereby slightly improving the performance. If we use innerHTML, React has no way to know the DOM is modified. The next time the render  happens, React will overwrite the content that was manually injected with what it thinks the correct state of that DOM node should be. That's where componentDidUpdate comes to rescue!

Share:
410,955

Related videos on Youtube

Jshoe523
Author by

Jshoe523

Updated on November 09, 2021

Comments

  • Jshoe523
    Jshoe523 over 2 years

    Is there any "behind the scenes" difference from setting an element's innerHTML vs setting the dangerouslySetInnerHTML property on an element? Assume I'm properly sanitizing things for the sake of simplicity.

    Example:

    var test = React.createClass({
      render: function(){
        return (
          <div contentEditable='true' dangerouslySetInnerHTML={{ __html: "Hello" }}></div>
        );
      }
    });
    

    vs

    var test = React.createClass({
      componentDidUpdate: function(prevProp, prevState){
        this.refs.test.innerHTML = "Hello";
      },
      render: function(){
        return (
          <div contentEditable='true' ref='test'></div>
        );
      }
    });
    

    I'm doing something a bit more complicated than the above example, but the overall idea is the same

  • Joscha
    Joscha about 7 years
    I wrote a small, non-scientific perf test to show the difference between inlining an SVG and using dangerouslySetInnerHTML: webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - tuns out the innerHTML method is almost twice as fast (see console in the webpackbin)
  • Up209d
    Up209d about 6 years
    That's true and easy to predict. Since innerHTML is a native method that binds the SVG code directly to the DOM without considering anything. On the other hand, dangerouslySetInnerHTML is the method come from React that the SVG code has to be parsed as React Component children in prior to put them to virtual DOM and then render to the DOM.
  • mkb
    mkb over 4 years
    well according to docs it seems this is the only reason, still confused
  • Quentin
    Quentin over 4 years
    This doesn't answer the question.