J. Pedro Ribeiro

How to fix 'dangerouslySetInnerHTML did not match' error in React.js

December 27, 2022

console.log error message on a browser

This is an issue I come across every once in a while and it always takes me a couple hours to figure it out.

Replicating the issue

Let's say you have a React.js component that will render a paragraph of text coming from a CMS and that content can have HTML tags in it, like a WYSIWYG editor.

// MyTextComponent.js
function MyTextComponent(props) {
  return <p dangerouslySetInnerHTML={{ __html: props.content }} />;
}

// App.js
function App(props) {
  return (
    <div>
      <MyTextComponent content={props.content} />
    </div>
  );
}

The browser renders what you expect:

browser rendering the component

However, there's that warning in the console that says:

Warning: Prop `dangerouslySetInnerHTML` did not match. Server: "" Client: "<p>This is my paragraph.</p>" 

If you're using Next.js, you will get a nicer error message:

Next.js error message

What causes this warning?

On my example, the content passed to the component was <p>This is my paragraph.</p> which would be fine considering that we are using dangerouslySetInnerHTML to render the content.

However, the component is already wrapping the content in a <p> tag which, according to the HTML Spec, should only contain phrasing content.

The spec also says:

Paragraphs are block-level elements, and notably will automatically close if another

Here is a CodePen that illustrates and replicates this condition more clearly:

If you inspect the rendered paragraph, you will see the following:

paragraph with invalid nested tags

Which doesn't match what the server rendered <p>This is my paragraph.</p>.

How to fix it?

One solution is to change the wrapping element to a <div> instead of a <p>.

// MyTextComponent.js
function MyTextComponent(props) {
  return <div dangerouslySetInnerHTML={{ __html: props.content }} />;
}   

The main point is to ensure that the rendered content is valid HTML.