Skip to content

Ignore CR/LF differences when warning about markup mismatch - #11119

Merged
gaearon merged 15 commits into
react:masterfrom
gaearon:whitespace-server
Oct 5, 2017
Merged

Ignore CR/LF differences when warning about markup mismatch#11119
gaearon merged 15 commits into
react:masterfrom
gaearon:whitespace-server

Conversation

@gaearon

@gaearon gaearon commented Oct 5, 2017

Copy link
Copy Markdown
Contributor

Fixes #11103.

According to the spec, HTML parser turns \r\n or lone \r into \n.

Since we compare JS app string (which might have \r) with the representation parsed from HTML (which can't), we have a false positive text mismatch warning.

I am solving this by adding a second check. It's only activated when we have a mismatch, so it only penalizes users with mismatching markup, or users with \r in content.

I opted not to patch up the markup when the only difference is \r normalization. This is because we never did that before, and nobody complained. So it's probably unobservable to the user anyway (even though it's observable from the DOM—you can't have \r by setting innerHTML or parsing, but you can if you createTextNodes with it directly).

An alternative could be to always normalize \r when creating text nodes (and patch up markup if we encounter it). This would also make the behavior consistent between innerHTML and createTextNode path on the client side.

It seems like we can always do the latter if we want to, but the former is an unobtrusive fix that can be applied now.

Updated it to just ignore the warning, but still patch up. Production logic doesn't change now.

Later updated to normalize both server and client values before emitting the warning. I started stripping both null and "replacement" character (browser sometimes turns null into it) since that's the only other corner case I know.

@reactjs-bot

reactjs-bot commented Oct 5, 2017

Copy link
Copy Markdown

Deploy preview ready!

Built with commit 72e67ff

https://deploy-preview-11119--reactjs.netlify.com

@gaearon

gaearon commented Oct 5, 2017

Copy link
Copy Markdown
Contributor Author

I haven’t thought about attributes though. I guess they also need it.

@sebmarkbage sebmarkbage left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If all you want to do is ignore the warning your logic should be able to be self-contained completely in warnForTextDifference and fully behind a __DEV__ flag so we don't need to ship this logic nor use it in production.

I.e. we shouldn't need to change the behavior of the isDifferent flag if we don't expect to patch it up.

if (normalizedClientText === serverText) {
return false;
}
return true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This return value is meant to indicate that it should patch it up. So this says that we will patch up the DOM if it differs, which is not what your comment says.

@gaearon gaearon changed the title Normalize line endings when comparing hydrated markup Ignore CR/LF differences when warning about markup mismatch Oct 5, 2017

@aickin aickin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. I love the test cases especially!

var normalizeMarkupForTextOrAttribute = function(markup: mixed): string {
const markupString = typeof markup === 'string'
? markup
: '' + (markup: any);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not super proud but I couldn't get Flow to understand I'm just trying to cast to string.

@vjeux vjeux Oct 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String(markup)

@gaearon

gaearon commented Oct 5, 2017

Copy link
Copy Markdown
Contributor Author

They took some head scratching 😛

@gaearon
gaearon merged commit 44c32fc into react:master Oct 5, 2017
@syranide

syranide commented Oct 7, 2017

Copy link
Copy Markdown
Contributor

@Gaeron I think there's a "bug" here, if you render \r\0 in some browsers it should still emit the message because they actually do support the null-character. In the DOM it will then be \n\0 whereas you will compare with \n as expected. So you should probably filter both strings for the null-character at the very least.

Nvm, failed my reading comprehension of the source code.

@gaearon

gaearon commented Oct 7, 2017

Copy link
Copy Markdown
Contributor Author

I believe the PR normalises both now.

mrizwanashiq pushed a commit to mrizwanashiq/react that referenced this pull request Jun 25, 2026
)

* Add regression test for CR-insensitive hydration

* Normalize CR when comparing server HTML to DOM

* Move tests in the file

* Add a failing test for comparing attributes

* Normalize CR for attributes too

* Add a test case for CR in dangerouslySetInnerHTML

* Undo the fix per feedback

* Change the fix to be DEV-only and still patch up LF -> CR

* Remove the dangerouslySetInnerHTML test

It's always going to "pass" because we normalize HTML anyway.

Except that it won't pass because we intentionally don't patch up dangerouslyInnerHTML.

* Fix issue that Flow failed to catch

* Add null character tests

* Normalize both client and server value for the warning

* Fix the bug

* Normalize replacement character away as well

* Fix outdated comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSR: ReactDOM client and server handling newlines differently causing mismatch warnings

8 participants