Implement findDOMNode for Fiber

This is the naive implementation that doesn't cover the case where there are
two diverging fibers, or if this tree is unmounted.
This commit is contained in:
Sebastian Markbage
2016-10-25 13:59:31 -07:00
parent e3131c1d55
commit 298d0c3e05
3 changed files with 83 additions and 4 deletions
+12
View File
@@ -146,6 +146,18 @@ var ReactDOM = {
}
},
findDOMNode(componentOrElement : Element | ?ReactComponent<any, any, any>) : null | Element | Text {
if (componentOrElement == null) {
return null;
}
// Unsound duck typing.
const component = (componentOrElement : any);
if (component.nodeType === 1) {
return component;
}
return DOMRenderer.findHostInstance(component);
},
};
module.exports = ReactDOM;
@@ -24,6 +24,8 @@ if (__DEV__) {
var ReactFiberInstrumentation = require('ReactFiberInstrumentation');
}
var { findCurrentHostFiber } = require('ReactFiberTreeReflection');
type Deadline = {
timeRemaining : () => number
};
@@ -58,17 +60,20 @@ export type HostConfig<T, P, I, TI, C> = {
type OpaqueNode = Fiber;
export type Reconciler<C, I> = {
export type Reconciler<C, I, TI> = {
mountContainer(element : ReactElement<any>, containerInfo : C) : OpaqueNode,
updateContainer(element : ReactElement<any>, container : OpaqueNode) : void,
unmountContainer(container : OpaqueNode) : void,
performWithPriority(priorityLevel : PriorityLevel, fn : Function) : void,
// Used to extract the return value from the initial render. Legacy API.
getPublicRootInstance(container : OpaqueNode) : (ReactComponent<any, any, any> | I | null),
getPublicRootInstance(container : OpaqueNode) : (ReactComponent<any, any, any> | TI | I | null),
// Use for findDOMNode/findHostNode. Legacy API.
findHostInstance(component : ReactComponent<any, any, any>) : I | TI | null,
};
module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) : Reconciler<C, I> {
module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) : Reconciler<C, I, TI> {
var { scheduleWork, performWithPriority } = ReactFiberScheduler(config);
@@ -122,7 +127,7 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) :
performWithPriority,
getPublicRootInstance(container : OpaqueNode) : (ReactComponent<any, any, any> | I | null) {
getPublicRootInstance(container : OpaqueNode) : (ReactComponent<any, any, any> | I | TI | null) {
const root : FiberRoot = (container.stateNode : any);
const containerFiber = root.current;
if (!containerFiber.child) {
@@ -131,6 +136,14 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) :
return containerFiber.child.stateNode;
},
findHostInstance(component : ReactComponent<any, any, any>) : I | TI | null {
const fiber = findCurrentHostFiber(component);
if (!fiber) {
return null;
}
return fiber.stateNode;
},
};
};
@@ -0,0 +1,54 @@
/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactFiberTreeReflection
* @flow
*/
'use strict';
import type { Fiber } from 'ReactFiber';
var ReactInstanceMap = require('ReactInstanceMap');
var {
ClassComponent,
HostContainer,
HostComponent,
HostText,
} = require('ReactTypeOfWork');
exports.findCurrentHostFiber = function(component : ReactComponent<any, any, any>) : Fiber | null {
var parent : ?Fiber = ReactInstanceMap.get(component);
if (!parent) {
return null;
}
// TODO: This search is incomplete because this could be one of two possible fibers.
let node : Fiber = parent;
while (true) {
if (node.tag === HostComponent || node.tag === HostText) {
return node;
} else if (node.child) {
// TODO: Coroutines need to visit the stateNode.
node = node.child;
continue;
}
if (node === parent) {
return null;
}
while (!node.sibling) {
if (!node.return || node.return === parent) {
return null;
}
node = node.return;
}
node = node.sibling;
}
return null;
};