336

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

7 Answers 7

409

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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.
Is there a way to let React know ignore the children of said element without explicitly using and setting something with dangerouslySetInnerHTML? Like if I want to set it later from some other function.
53

You can bind to dom directly

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

Comments

22

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.

2 Comments

This doesn't answer the question.
The example is strange because it actually uses a function createMarkup instead of an object, especially when the permformance is mentioned. Just my two cents.
8

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!

Comments

3

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

1 Comment

well according to docs it seems this is the only reason, still confused
0

Good explanations on the diffing and performance parts, but missing a few points. content set with dangerouslySetInnerHTML isn’t managed by React (no React event handlers inside), and using innerHTML directly breaks React’s declarative model. Also note possible SSR/hydration mismatches and that the __html object is intentional to force explicit use.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
-3

Yes, there is a significant difference between setting an element's innerHTML directly and using the dangerouslySetInnerHTML property in React. These differences are primarily related to security, React's rendering behavior, and how the DOM is updated.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.