Skip to content

React 16 fails to rehydrate noscripts #10993

Closed
@wchargin

Description

@wchargin

Do you want to request a feature or report a bug?
Bug.

What is the current behavior?
As of React 16, <noscript dangerouslySetInnerHTML={...} />s are not properly rehydrated. Equivalent code works in React 15.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/ebsrpraL/).
Consider the following server-side code:

const React = require('react');
const ReactDOMServer = require('react-dom/server');

class Main extends React.Component {

    render() {
        const component = React.createElement('strong', {}, 'Hello!');
        const contents = ReactDOMServer.renderToStaticMarkup(component);
        console.log("--- Contents: " + contents);
        return React.createElement('noscript', {
            dangerouslySetInnerHTML: {__html: contents},
        }, null);
    }

}

function createApp() {
    return React.createElement(Main, {}, null);
}

console.log(ReactDOMServer.renderToString(createApp()));

This code works fine in Reacts 15 and 16 alike; the outputs are similar:

// React 15
--- Contents: <strong>Hello!</strong>
<noscript data-reactroot="" data-reactid="1" data-react-checksum="1795300394"><strong>Hello!</strong></noscript>

// React 16
--- Contents: <strong>Hello!</strong>
<noscript data-reactroot=""><strong>Hello!</strong></noscript>

Now, consider the following application (jsbin):

<!DOCTYPE html>
<html>
<body>

<!-- React 16 (exhibits bug) -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<!-- React 15 (does not exhibit bug) -->
<!--
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.js"></script>
-->


<div id="target"><noscript data-reactroot=""><strong>Hello!</strong></noscript></div>

<script>
class Main extends React.Component {

    render() {
        const contents = '<strong>Hello!</strong>';
        console.log("--- Contents: " + contents);
        return React.createElement('noscript', {
            dangerouslySetInnerHTML: {__html: contents},
        }, null);
    }

}

function createApp() {
    return React.createElement(Main, {}, null);
}

(ReactDOM.hydrate || ReactDOM.render)(
    createApp(), document.getElementById('target'));

console.log("Initialized.");
</script>

</body>
</html>

In React 16, this displays the following in the console:

[log] --- Contents: <strong>Hello!</strong>
[err] Warning: Prop `dangerouslySetInnerHTML` did not match. Server: "&lt;strong&gt;Hello!&lt;/strong&gt;" Client: "<strong>Hello!</strong>"
[log] Initialized.

If you swap the comment blocks in the HTML so that React 15 is used, the code works just fine: there are no warnings. (This is true regardless of whether you change the contents of div#target from the React 16 output to the React 15 output.)

The error message confuses me; it states that the server output is

&lt;strong&gt;Hello!&lt;/strong&gt;

but this is not consistent with the output of the server-side code (neither the "Contents" nor the final markup emitted has HTML entities).

Please note that this is important because it breaks the only known workaround to #1252.

I believe that this may be specific to noscripts, because if one replaces all occurrences of noscript with div then the example works fine in React 16.

What is the expected behavior?
Rendering a component with renderToString and then rehydrating that component verbatim should not yield an error.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
Regression from 15 to 16. Tested in Chrome v61.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions