-
Notifications
You must be signed in to change notification settings - Fork 47.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Print attributes in hydration errors #24167
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,6 +100,7 @@ let warnForInvalidEventListener; | |
let canDiffStyleForHydrationWarning; | ||
|
||
let normalizeHTML; | ||
let formatTagDEV; | ||
|
||
if (__DEV__) { | ||
warnedUnknownTags = { | ||
|
@@ -206,6 +207,26 @@ if (__DEV__) { | |
testElement.innerHTML = html; | ||
return testElement.innerHTML; | ||
}; | ||
|
||
formatTagDEV = function(node: Element): string { | ||
let str = '<' + node.nodeName.toLowerCase(); | ||
const attributeNames = node.getAttributeNames(); | ||
for (let i = 0; i < attributeNames.length; i++) { | ||
if (i > 30) { | ||
str += ' ...'; | ||
break; | ||
} | ||
const attributeName = attributeNames[i]; | ||
const value = node.getAttribute(attributeName); | ||
let trimmedValue = value; | ||
if (value.length > 30) { | ||
trimmedValue = value.substr(0, 30) + '...'; | ||
} | ||
str += ' ' + attributeName + '="' + trimmedValue + '"'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't escape trimmedValue but I think that's fine. If we wanted to escape we'd need to move the escaping utility from the server folder or copypaste here. |
||
} | ||
str += '>'; | ||
return str; | ||
}; | ||
} | ||
|
||
// HTML parsing normalizes CR and CRLF to LF. | ||
|
@@ -1209,9 +1230,9 @@ export function warnForDeletedHydratableElement( | |
} | ||
didWarnInvalidHydration = true; | ||
console.error( | ||
'Did not expect server HTML to contain a <%s> in <%s>.', | ||
child.nodeName.toLowerCase(), | ||
parentNode.nodeName.toLowerCase(), | ||
'Did not expect server HTML to contain a %s in %s.', | ||
formatTagDEV(child), | ||
formatTagDEV(parentNode), | ||
); | ||
} | ||
} | ||
|
@@ -1226,9 +1247,9 @@ export function warnForDeletedHydratableText( | |
} | ||
didWarnInvalidHydration = true; | ||
console.error( | ||
'Did not expect server HTML to contain the text node "%s" in <%s>.', | ||
'Did not expect server HTML to contain the text node "%s" in %s.', | ||
child.nodeValue, | ||
parentNode.nodeName.toLowerCase(), | ||
formatTagDEV(parentNode), | ||
); | ||
} | ||
} | ||
|
@@ -1244,9 +1265,9 @@ export function warnForInsertedHydratedElement( | |
} | ||
didWarnInvalidHydration = true; | ||
console.error( | ||
'Expected server HTML to contain a matching <%s> in <%s>.', | ||
'Expected server HTML to contain a matching <%s> in %s.', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it clear what the "in" really means here? That's the thing that I always found vague. Like are these the mismatches, or is one parent and one child? I feel like the message you use some formatting. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I'd propose changing it more significantly. Something like
Thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has the same data but is easier to parse for me at least. More visual:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same format translates to missing and extra nodes too. |
||
tag, | ||
parentNode.nodeName.toLowerCase(), | ||
formatTagDEV(parentNode), | ||
); | ||
} | ||
} | ||
|
@@ -1268,9 +1289,9 @@ export function warnForInsertedHydratedText( | |
} | ||
didWarnInvalidHydration = true; | ||
console.error( | ||
'Expected server HTML to contain a matching text node for "%s" in <%s>.', | ||
'Expected server HTML to contain a matching text node for "%s" in %s.', | ||
text, | ||
parentNode.nodeName.toLowerCase(), | ||
formatTagDEV(parentNode), | ||
); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could get a React name for this but seems confusing. E.g. it would still print
style
as a string. So I figured it should just use HTML in the message.