Skip to content

Commit 1dea4f1

Browse files
mgoljetoneza
authored andcommitted
Make IE 11 not complain about non-crucial style attribute hydration mismatch (facebook#13534)
IE 11 parses & normalizes the style attribute as opposed to other browsers. It adds spaces and sorts the properties in some non-alphabetical order. Handling that would require sorting CSS properties in the client & server versions or applying `expectedStyle` to a temporary DOM node to read its `style` attribute normalized. Since it only affects IE, we're skipping style warnings in that browser completely in favor of doing all that work. Fixes facebook#11807
1 parent d4ea4f9 commit 1dea4f1

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

packages/react-dom/src/__tests__/ReactServerRenderingHydration.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,67 @@ describe('ReactDOMServerHydration', () => {
258258
expect(element.firstChild.focus).not.toHaveBeenCalled();
259259
});
260260

261+
it('should warn when the style property differs', () => {
262+
const element = document.createElement('div');
263+
element.innerHTML = ReactDOMServer.renderToString(
264+
<div style={{textDecoration: 'none', color: 'black', height: '10px'}} />,
265+
);
266+
expect(element.firstChild.style.textDecoration).toBe('none');
267+
expect(element.firstChild.style.color).toBe('black');
268+
269+
expect(() =>
270+
ReactDOM.hydrate(
271+
<div
272+
style={{textDecoration: 'none', color: 'white', height: '10px'}}
273+
/>,
274+
element,
275+
),
276+
).toWarnDev(
277+
'Warning: Prop `style` did not match. Server: ' +
278+
'"text-decoration:none;color:black;height:10px" Client: ' +
279+
'"text-decoration:none;color:white;height:10px"',
280+
{withoutStack: true},
281+
);
282+
});
283+
284+
it('should not warn when the style property differs on whitespace or order in IE', () => {
285+
document.documentMode = 11;
286+
const element = document.createElement('div');
287+
288+
// Simulate IE normalizing the style attribute. IE makes it equal to
289+
// what's available under `node.style.cssText`.
290+
element.innerHTML =
291+
'<div style="height: 10px; color: black; text-decoration: none;" data-reactroot=""></div>';
292+
293+
ReactDOM.hydrate(
294+
<div style={{textDecoration: 'none', color: 'black', height: '10px'}} />,
295+
element,
296+
);
297+
298+
delete document.documentMode;
299+
});
300+
301+
it('should warn when the style property differs on whitespace in non-IE browsers', () => {
302+
const element = document.createElement('div');
303+
304+
element.innerHTML =
305+
'<div style="text-decoration: none; color: black; height: 10px;" data-reactroot=""></div>';
306+
307+
expect(() =>
308+
ReactDOM.hydrate(
309+
<div
310+
style={{textDecoration: 'none', color: 'black', height: '10px'}}
311+
/>,
312+
element,
313+
),
314+
).toWarnDev(
315+
'Warning: Prop `style` did not match. Server: ' +
316+
'"text-decoration: none; color: black; height: 10px;" Client: ' +
317+
'"text-decoration:none;color:black;height:10px"',
318+
{withoutStack: true},
319+
);
320+
});
321+
261322
it('should throw rendering portals on the server', () => {
262323
const div = document.createElement('div');
263324
expect(() => {

packages/react-dom/src/client/ReactDOMComponent.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -999,12 +999,23 @@ export function diffHydratedProperties(
999999
} else if (propKey === STYLE) {
10001000
// $FlowFixMe - Should be inferred as not undefined.
10011001
extraAttributeNames.delete(propKey);
1002-
const expectedStyle = CSSPropertyOperations.createDangerousStringForStyles(
1003-
nextProp,
1004-
);
1005-
serverValue = domElement.getAttribute('style');
1006-
if (expectedStyle !== serverValue) {
1007-
warnForPropDifference(propKey, serverValue, expectedStyle);
1002+
1003+
// IE 11 parses & normalizes the style attribute as opposed to other
1004+
// browsers. It adds spaces and sorts the properties in some
1005+
// non-alphabetical order. Handling that would require sorting CSS
1006+
// properties in the client & server versions or applying
1007+
// `expectedStyle` to a temporary DOM node to read its `style` attribute
1008+
// normalized. Since it only affects IE, we're skipping style warnings
1009+
// in that browser completely in favor of doing all that work.
1010+
// See https://github.com/facebook/react/issues/11807
1011+
if (!document.documentMode) {
1012+
const expectedStyle = CSSPropertyOperations.createDangerousStringForStyles(
1013+
nextProp,
1014+
);
1015+
serverValue = domElement.getAttribute('style');
1016+
if (expectedStyle !== serverValue) {
1017+
warnForPropDifference(propKey, serverValue, expectedStyle);
1018+
}
10081019
}
10091020
} else if (isCustomComponentTag) {
10101021
// $FlowFixMe - Should be inferred as not undefined.

0 commit comments

Comments
 (0)