Skip to content

[Fiber] Implement findDOMNode and isMounted #8083

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 6 commits into from
Oct 26, 2016

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Oct 24, 2016

The strategy of finding the "current" through the back pointers turned out to be inefficient. You basically have to scan from the top to find them since the return pointer is active even when a child is in progressedChild instead of child.

isMounted is pretty easy though since we can just cut off the return pointer when a child gets deleted.

The key realization to fix findDOMNode is the realization that it doesn't matter which one is current if there is no pending insertion / previous deletion. So we can just check for those to determine if we're looking in the wrong tree.

I'm not too worried about this being understandable unless we have other use cases for "reflection" that are less deprecated.

Also note two new features: findDOMNode in fragment returns first child rather than error/null. Just like element.querySelector. findDOMNode when a component returns a string, finds the host text node. This is the first time you could get access to a text node instance. It's not super great since if the text node merges (due to normalization) then it could actually represent multiple text nodes, but maybe that's fine. Seems useful.

@@ -54,17 +56,20 @@ export type HostConfig<T, P, I, TI, C> = {

type OpaqueNode = Fiber;

export type Reconciler<C, I> = {
export type Reconciler<C, I, TI> = {
Copy link
Contributor

Choose a reason for hiding this comment

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

TI ~= TextInstance?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yea

break;
}
case PlacementAndUpdate: {
commitInsertion(effectfulFiber);
const current = effectfulFiber.alternate;
commitWork(current, effectfulFiber);
// Clear the effect tag so that we know that this is inserted, before
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this supposed to be the same comment as above? How is setting the effectTag to Update equal to clearing it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Clearing the "placement" part of it.

This is the naive implementation that doesn't cover the case where there are
two diverging fibers, or if this tree is unmounted.
This is the naive implementation that doesn't cover the case
where it has completed but not yet committed. It also doesn't
deal with unmounts since they currently don't clean up the item
in the ReactInstanceMap.
This will let us use these pointers to reason about a tree.
Whether if it is "current" or "work in progress".
There are two cases where we have a Fiber that is not actually
mounted. Either it is part of a tree that has not yet been
inserted or it is part of a tree that was unmounted.

For the insertion case, we can check the parents to see if there
is any insertion effect pending along the parent path.

For deletions, we can now check if any of the return pointers
is null without actually being the root.
First we need to check if a component subtree is mounted at all.

If it is, we need to search down the fiber for the first host
node. However, we might be searching the "work in progress"
instead of current.

One realization is that it doesn't matter if we search work in
progress or current if they're the same. They will generally be
the same unless there is an insertion pending or something in
the alternate tree was already deleted. So if we find one of
those cases, we switch to look in the alternate tree instead.
These are new features that aren't covered by existing tests.

It is now possible to use findDOMNode to find a text node.

When a component returns a fragment, it will search to find the
first host component just like element.querySelector does.
@acdlite
Copy link
Collaborator

acdlite commented Oct 26, 2016

Yay

@sebmarkbage sebmarkbage merged commit 7bcad0a into facebook:master Oct 26, 2016
@@ -156,6 +162,8 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
// and lastEffect since they're on every node, not just the effectful
// ones. So we have to clean everything as we reuse nodes anyway.
effectfulFiber.nextEffect = null;
// Ensure that we reset the effectTag here so that we can rely on effect
// tags to reason about the current life-cycle.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment doesn't apply to the line below anymore. It used to refer to effectTag assignment which has been moved.

node = parent = parent.alternate;
continue;
}
if (node.tag === HostComponent || node.tag === HostText) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this mean if you render two host components as a fragment then this method will return the first?

Copy link
Collaborator Author

@sebmarkbage sebmarkbage Oct 26, 2016

Choose a reason for hiding this comment

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

Yes. I figured that it would be unnecessary to keep searching for the second one to force an error. The last commit adds a test for this. 8e2d7f8#diff-7556f354e68e9c4454dbd21aedf610dfR87

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants