From b14d38af3b6f4cbe63bd80dae1bf62498b487711 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Apr 2020 12:26:23 +0200 Subject: [PATCH 1/6] test: Add failing case for dangerouslySetInnerHtml=undefined --- .../ReactServerRenderingHydration-test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js index 14dbe62d3996..b622598c7d96 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js @@ -548,4 +548,20 @@ describe('ReactDOMServerHydration', () => { expect(ref.current).toBe(div); expect(element.innerHTML).toBe('
Hello World
'); }); + + // regression test for https://github.com/facebook/react/issues/17170 + it('should not warn if dangerouslySetInnerHtml=undefined', () => { + const domElement = document.createElement('div'); + const reactElement = ( +
+

Hello, World!

+
+ ); + const markup = ReactDOMServer.renderToStaticMarkup(reactElement); + domElement.innerHTML = markup; + + ReactDOM.hydrate(reactElement, domElement); + + expect(domElement.innerHTML).toEqual(markup); + }); }); From 47c0e9e4c146ec53d09b6a7f1c7cd62b7b9d045c Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Apr 2020 12:43:38 +0200 Subject: [PATCH 2/6] fix: skip dangerouslySetInnerHtml warning if it's undefined --- packages/react-dom/src/client/ReactDOMComponent.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/react-dom/src/client/ReactDOMComponent.js b/packages/react-dom/src/client/ReactDOMComponent.js index 539d53b781c9..8e2d1605e547 100644 --- a/packages/react-dom/src/client/ReactDOMComponent.js +++ b/packages/react-dom/src/client/ReactDOMComponent.js @@ -1110,12 +1110,14 @@ export function diffHydratedProperties( } else if (propKey === DANGEROUSLY_SET_INNER_HTML) { const serverHTML = domElement.innerHTML; const nextHtml = nextProp ? nextProp[HTML] : undefined; - const expectedHTML = normalizeHTML( - domElement, - nextHtml != null ? nextHtml : '', - ); - if (expectedHTML !== serverHTML) { - warnForPropDifference(propKey, serverHTML, expectedHTML); + if (nextHtml != null) { + const expectedHTML = normalizeHTML( + domElement, + nextHtml != null ? nextHtml : '', + ); + if (expectedHTML !== serverHTML) { + warnForPropDifference(propKey, serverHTML, expectedHTML); + } } } else if (propKey === STYLE) { // $FlowFixMe - Should be inferred as not undefined. From b72da4e256f37402f2387663802fbd730a735ddd Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Apr 2020 12:49:06 +0200 Subject: [PATCH 3/6] test: add similar test that should trigger the warning --- .../ReactServerRenderingHydration-test.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js index b622598c7d96..419fda91e269 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js @@ -564,4 +564,25 @@ describe('ReactDOMServerHydration', () => { expect(domElement.innerHTML).toEqual(markup); }); + + it('should warns if innerHTML mismatches with dangerouslySetInnerHTML=undefined on the client', () => { + const domElement = document.createElement('div'); + const markup = ReactDOMServer.renderToStaticMarkup( +
server

'}} />, + ); + domElement.innerHTML = markup; + + expect(() => { + ReactDOM.hydrate( +
+

client

+
, + domElement, + ); + + expect(domElement.innerHTML).not.toEqual(markup); + }).toErrorDev( + 'Warning: Text content did not match. Server: "server" Client: "client"', + ); + }); }); From 5badbd94339114f8e8b2f7fa785718c79e6cda56 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Apr 2020 12:54:34 +0200 Subject: [PATCH 4/6] chore: Remove redundant nullish check --- packages/react-dom/src/client/ReactDOMComponent.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/react-dom/src/client/ReactDOMComponent.js b/packages/react-dom/src/client/ReactDOMComponent.js index 8e2d1605e547..808f90153690 100644 --- a/packages/react-dom/src/client/ReactDOMComponent.js +++ b/packages/react-dom/src/client/ReactDOMComponent.js @@ -1111,10 +1111,7 @@ export function diffHydratedProperties( const serverHTML = domElement.innerHTML; const nextHtml = nextProp ? nextProp[HTML] : undefined; if (nextHtml != null) { - const expectedHTML = normalizeHTML( - domElement, - nextHtml != null ? nextHtml : '', - ); + const expectedHTML = normalizeHTML(domElement, nextHtml); if (expectedHTML !== serverHTML) { warnForPropDifference(propKey, serverHTML, expectedHTML); } From 63387c2e92e641ab7b7e91f8f779f723589b6e5a Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Apr 2020 13:20:28 +0200 Subject: [PATCH 5/6] Poke yarn_test_www_variant which timed out From 5c058570309bb8e595a3713b5f6314173d9eed32 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Apr 2020 17:15:27 +0200 Subject: [PATCH 6/6] test: Add smaller test for innerHTML=string to innerHTML=undefined --- .../ReactServerRenderingHydration-test.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js index 419fda91e269..770740e59102 100644 --- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js +++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js @@ -565,7 +565,7 @@ describe('ReactDOMServerHydration', () => { expect(domElement.innerHTML).toEqual(markup); }); - it('should warns if innerHTML mismatches with dangerouslySetInnerHTML=undefined on the client', () => { + it('should warn if innerHTML mismatches with dangerouslySetInnerHTML=undefined and children on the client', () => { const domElement = document.createElement('div'); const markup = ReactDOMServer.renderToStaticMarkup(
server

'}} />, @@ -585,4 +585,20 @@ describe('ReactDOMServerHydration', () => { 'Warning: Text content did not match. Server: "server" Client: "client"', ); }); + + it('should warn if innerHTML mismatches with dangerouslySetInnerHTML=undefined on the client', () => { + const domElement = document.createElement('div'); + const markup = ReactDOMServer.renderToStaticMarkup( +
server

'}} />, + ); + domElement.innerHTML = markup; + + expect(() => { + ReactDOM.hydrate(
, domElement); + + expect(domElement.innerHTML).not.toEqual(markup); + }).toErrorDev( + 'Warning: Did not expect server HTML to contain a

in

', + ); + }); });