mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Utilize the backtracking during events to figure out if a Fiber was unmounted
We're walking backwards up to the root to find the parent so that we can propagate events further up to nested React parents. If we don't find a root, that means that the tree was unmounted and we shouldn't send any events to it.
This commit is contained in:
@@ -42,9 +42,6 @@ src/renderers/dom/shared/__tests__/ReactDOMTextComponent-test.js
|
||||
* can reconcile text arbitrarily split into multiple nodes
|
||||
* can reconcile text arbitrarily split into multiple nodes on some substitutions only
|
||||
|
||||
src/renderers/dom/shared/__tests__/ReactEventIndependence-test.js
|
||||
* does not when event fired on unmounted tree
|
||||
|
||||
src/renderers/dom/shared/__tests__/ReactEventListener-test.js
|
||||
* should batch between handlers from different roots
|
||||
|
||||
|
||||
@@ -640,6 +640,7 @@ src/renderers/dom/shared/__tests__/ReactDOMTextComponent-test.js
|
||||
src/renderers/dom/shared/__tests__/ReactEventIndependence-test.js
|
||||
* does not crash with other react inside
|
||||
* does not crash with other react outside
|
||||
* does not when event fired on unmounted tree
|
||||
|
||||
src/renderers/dom/shared/__tests__/ReactEventListener-test.js
|
||||
* should dispatch events from outside React tree
|
||||
|
||||
@@ -16,33 +16,38 @@ var ExecutionEnvironment = require('ExecutionEnvironment');
|
||||
var PooledClass = require('PooledClass');
|
||||
var ReactDOMComponentTree = require('ReactDOMComponentTree');
|
||||
var ReactGenericBatching = require('ReactGenericBatching');
|
||||
var ReactTypeOfWork = require('ReactTypeOfWork');
|
||||
|
||||
var getEventTarget = require('getEventTarget');
|
||||
var getUnboundedScrollPosition = require('getUnboundedScrollPosition');
|
||||
|
||||
var { HostContainer } = ReactTypeOfWork;
|
||||
|
||||
/**
|
||||
* Find the deepest React component completely containing the root of the
|
||||
* passed-in instance (for use when entire React trees are nested within each
|
||||
* other). If React trees are not nested, returns null.
|
||||
*/
|
||||
function findParent(inst) {
|
||||
function findRootContainerNode(inst) {
|
||||
// TODO: It may be a good idea to cache this to prevent unnecessary DOM
|
||||
// traversal, but caching is difficult to do correctly without using a
|
||||
// mutation observer to listen for all DOM changes.
|
||||
var container;
|
||||
if (typeof inst.tag === 'number') {
|
||||
while (inst.return) {
|
||||
inst = inst.return;
|
||||
}
|
||||
container = inst.stateNode.containerInfo;
|
||||
if (inst.tag !== HostContainer) {
|
||||
// This can happen if we're in a detached tree.
|
||||
return null;
|
||||
}
|
||||
return inst.stateNode.containerInfo;
|
||||
} else {
|
||||
while (inst._hostParent) {
|
||||
inst = inst._hostParent;
|
||||
}
|
||||
var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);
|
||||
container = rootNode.parentNode;
|
||||
return rootNode.parentNode;
|
||||
}
|
||||
return ReactDOMComponentTree.getClosestInstanceFromNode(container);
|
||||
}
|
||||
|
||||
// Used to store ancestor hierarchy in top level callback
|
||||
@@ -74,8 +79,18 @@ function handleTopLevelImpl(bookKeeping) {
|
||||
// inconsistencies with ReactMount's node cache. See #1105.
|
||||
var ancestor = targetInst;
|
||||
do {
|
||||
if (!ancestor) {
|
||||
bookKeeping.ancestors.push(ancestor);
|
||||
break;
|
||||
}
|
||||
var root = findRootContainerNode(ancestor);
|
||||
if (!root) {
|
||||
break;
|
||||
}
|
||||
bookKeeping.ancestors.push(ancestor);
|
||||
ancestor = ancestor && findParent(ancestor);
|
||||
ancestor = ReactDOMComponentTree.getClosestInstanceFromNode(
|
||||
root
|
||||
);
|
||||
} while (ancestor);
|
||||
|
||||
for (var i = 0; i < bookKeeping.ancestors.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user