Skip to content

Commit

Permalink
Make IE 11 not complain about non-crucial style attribute hydration m…
Browse files Browse the repository at this point in the history
…ismatch

IE 11 parses & normalizes the style attribute as opposed to other browsers.
The normalization added in this commit normalizes spacing which resolves most
irrelevant style prop warnings, though a warning will still happen if the style
attribute contains invalid CSS declarations.

Fixes #11807
  • Loading branch information
mgol committed Sep 2, 2018
1 parent 28b9289 commit 0b0e01f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
39 changes: 39 additions & 0 deletions packages/react-dom/src/__tests__/ReactServerRenderingHydration.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,45 @@ describe('ReactDOMServerHydration', () => {
expect(element.firstChild.focus).not.toHaveBeenCalled();
});

it('should warn when the style property differs', () => {
const element = document.createElement('div');
element.innerHTML = ReactDOMServer.renderToString(
<div style={{textDecoration: 'none', color: 'black'}} />,
);
expect(element.firstChild.style.textDecoration).toBe('none');
expect(element.firstChild.style.color).toBe('black');

expect(() =>
ReactDOM.hydrate(
<div style={{textDecoration: 'none', color: 'white'}} />,
element,
),
).toWarnDev(
'Warning: Prop `style` did not match. Server: ' +
'"text-decoration:none;color:black" Client: ' +
'"text-decoration:none;color:white"',
{withoutStack: true},
);
});

it('should not warn when the style property differs on whitespace only', () => {
const element = document.createElement('div');
element.innerHTML = ReactDOMServer.renderToString(
<div style={{textDecoration: 'none', color: 'black'}} />,
);
expect(element.firstChild.style.textDecoration).toBe('none');
expect(element.firstChild.style.color).toBe('black');

spyOnDevAndProd(console, 'error');

ReactDOM.hydrate(
<div style={{textDecoration: 'none', color: 'black'}} />,
element,
);

expect(console.error).not.toHaveBeenCalled();
});

it('should throw rendering portals on the server', () => {
const div = document.createElement('div');
expect(() => {
Expand Down
18 changes: 16 additions & 2 deletions packages/react-dom/src/client/ReactDOMFiberComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,24 @@ if (__DEV__) {
const NORMALIZE_NEWLINES_REGEX = /\r\n?/g;
const NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;

normalizeMarkupForTextOrAttribute = function(markup: mixed): string {
normalizeMarkupForTextOrAttribute = function(
markup: mixed,
propName?: string,
): string {
const markupString =
typeof markup === 'string' ? markup : '' + (markup: any);
return markupString
const markupNormalized = markupString
.replace(NORMALIZE_NEWLINES_REGEX, '\n')
.replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');
if (propName !== 'style') {
return markupNormalized;
}
// IE 11 parses & normalizes the style attribute as opposed to other
// browsers. The following normalization will still fail if the style
// attribute contains invalid CSS declarations but the majority of
// false warnings comes from spacing issues.
// See https://github.com/facebook/react/issues/11807
return markupNormalized.replace(/\s*([:;])\s*/, '$1').replace(/;$/, '');
};

warnForTextDifference = function(
Expand Down Expand Up @@ -141,9 +153,11 @@ if (__DEV__) {
}
const normalizedClientValue = normalizeMarkupForTextOrAttribute(
clientValue,
propName,
);
const normalizedServerValue = normalizeMarkupForTextOrAttribute(
serverValue,
propName,
);
if (normalizedServerValue === normalizedClientValue) {
return;
Expand Down

0 comments on commit 0b0e01f

Please sign in to comment.