From 0b0e01f8093673c654a67a2f9014813a9e8b3197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82e=CC=A8biowski-Owczarek?= Date: Sun, 2 Sep 2018 01:10:44 +0200 Subject: [PATCH] Make IE 11 not complain about non-crucial style attribute hydration mismatch 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 --- .../ReactServerRenderingHydration.js | 39 +++++++++++++++++++ .../src/client/ReactDOMFiberComponent.js | 18 ++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js index 63a0104f0cc60..5a20146ff821e 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration.js @@ -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( +
, + ); + expect(element.firstChild.style.textDecoration).toBe('none'); + expect(element.firstChild.style.color).toBe('black'); + + expect(() => + ReactDOM.hydrate( +
, + 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( +
, + ); + expect(element.firstChild.style.textDecoration).toBe('none'); + expect(element.firstChild.style.color).toBe('black'); + + spyOnDevAndProd(console, 'error'); + + ReactDOM.hydrate( +
, + element, + ); + + expect(console.error).not.toHaveBeenCalled(); + }); + it('should throw rendering portals on the server', () => { const div = document.createElement('div'); expect(() => { diff --git a/packages/react-dom/src/client/ReactDOMFiberComponent.js b/packages/react-dom/src/client/ReactDOMFiberComponent.js index 11d491572c1d8..5d8a9b2fb67e9 100644 --- a/packages/react-dom/src/client/ReactDOMFiberComponent.js +++ b/packages/react-dom/src/client/ReactDOMFiberComponent.js @@ -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( @@ -141,9 +153,11 @@ if (__DEV__) { } const normalizedClientValue = normalizeMarkupForTextOrAttribute( clientValue, + propName, ); const normalizedServerValue = normalizeMarkupForTextOrAttribute( serverValue, + propName, ); if (normalizedServerValue === normalizedClientValue) { return;