-
Notifications
You must be signed in to change notification settings - Fork 50.2k
DOM diff and component stack in SSR hydrate mismatch warnings (#10085) #12063
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
Changes from 1 commit
a11486a
6fc330d
283a56c
7ea192a
3aec458
9050bc5
bec7032
8b9be96
949f2de
2240ab9
31d7c85
b8c5b9d
221bc1f
1a15f08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -106,8 +106,30 @@ function insertNonHydratedInstance( | |
| ) { | ||
| fiber.effectTag |= Placement; | ||
| if (__DEV__) { | ||
| // TODO: Find out what `hydrationWarningHostInstanceIndex` should be, `fiber.index` is wrong. | ||
| const hydrationWarningHostInstanceIndex = fiber.index; | ||
| let hydrationWarningHostInstanceIndex = 0; | ||
| { | ||
| // Count rendered host nodes by traversing `returnFiber` subtree until `fiber` is found. | ||
| let node = returnFiber.child; | ||
| const nextNodeStack = []; | ||
| while (node && node !== fiber) { | ||
| if (node.tag === HostComponent || node.tag === HostText) { | ||
| ++hydrationWarningHostInstanceIndex; | ||
| } | ||
| // Depth-first traversal. | ||
| if (node.child) { | ||
| if (node.sibling) { | ||
| // Remember where to continue on this tree level, then go deeper. | ||
| nextNodeStack.push(node.sibling); | ||
| } | ||
| node = node.child; | ||
| } else if (node.sibling) { | ||
| node = node.sibling; | ||
| } else { | ||
| node = nextNodeStack.pop(); | ||
| } | ||
| } | ||
| } | ||
|
Collaborator
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. Can you please describe this algorithm in words? What is it looking for in particular? Specifically I wonder if you can avoid the need for
Collaborator
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. OK, I think I see what you're doing. You're starting the search at the return fiber, and then looking for this fiber, counting how many host children there appear to be between them. I think you can still avoid
Contributor
Author
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. Yes, I saw the traversal variant with writing into the return pointers but I thought it would be unsafe to modify the structure owned and maintained by another piece of code. If return pointers are only used during one traversal and their previous state is not relied upon, I can rewrite to use them instead of the stack. Said that, this traversal is not performance-critical as it happens only in development mode and only when hydration failed.
Collaborator
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, we rely on this pretty much everywhere.
Agree but would prefer consistency since that's how we traverse elsewhere. |
||
|
|
||
| switch (returnFiber.tag) { | ||
| case HostRoot: { | ||
| const parentContainer = returnFiber.stateNode.containerInfo; | ||
|
|
||

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.
If a node is a host component, why do we need to go inside of it? I imagine we'd want to skip over it to search for the next one. Otherwise we'd count its children (which we shouldn't). Am I wrong?
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.
Yes I just had this thought, too, while drawing the diagram. Should it not have children by definition though?
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.
Why not?
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.
Okay, I think I got it: if a HostComponent is e.g. a div, it may have children. Then we should only count children-less HostComponents and HostTexts.
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.
Why shouldn’t we couldn’t them?
I think we should count them regardless of whether they have children or not. We just shouldn’t descend into them because their children have no effect on the index.
That said see my comment below.
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.
Yes, you're right. I assumed we need to count leaf host nodes, but in fact we need to count only the parent's immediate children host nodes. Thanks for the repro test case.