diff --git a/packages/react-dom/src/client/ReactDOMComponentTree.js b/packages/react-dom/src/client/ReactDOMComponentTree.js index fbf0a81e29064..ba72082a1706a 100644 --- a/packages/react-dom/src/client/ReactDOMComponentTree.js +++ b/packages/react-dom/src/client/ReactDOMComponentTree.js @@ -33,9 +33,11 @@ import {getParentSuspenseInstance} from './ReactDOMHostConfig'; import invariant from 'shared/invariant'; import {enableScopeAPI} from 'shared/ReactFeatureFlags'; -const randomKey = Math.random() - .toString(36) - .slice(2); +// const randomKey = Math.random() +// .toString(36) +// .slice(2); +// HACK: not so random anymore +const randomKey = ''; const internalInstanceKey = '__reactFiber$' + randomKey; const internalPropsKey = '__reactProps$' + randomKey; const internalContainerInstanceKey = '__reactContainer$' + randomKey; diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js index 4e9acfae11356..d55125670c597 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js @@ -1044,7 +1044,7 @@ function commitUnmount( } while (effect !== firstEffect); } } - return; + break; } case ClassComponent: { safelyDetachRef(current, nearestMountedAncestor); @@ -1056,11 +1056,28 @@ function commitUnmount( nearestMountedAncestor, ); } - return; + break; } case HostComponent: { safelyDetachRef(current, nearestMountedAncestor); - return; + // HACK: detach fiber references from DOM + current.stateNode.__reactFiber$ = null; + current.stateNode.__reactProps$ = null; + current.stateNode.__reactContainer$ = null; + current.stateNode.__reactEvents$ = null; + current.stateNode.__reactListeners$ = null; + current.stateNode.__reactHandles$ = null; + break; + } + case HostText: { + // HACK: detach fiber references from DOM + current.stateNode.__reactFiber$ = null; + current.stateNode.__reactProps$ = null; + current.stateNode.__reactContainer$ = null; + current.stateNode.__reactEvents$ = null; + current.stateNode.__reactListeners$ = null; + current.stateNode.__reactHandles$ = null; + break; } case HostPortal: { // TODO: this is recursive. @@ -1076,7 +1093,7 @@ function commitUnmount( } else if (supportsPersistence) { emptyPortalContainer(current); } - return; + break; } case FundamentalComponent: { if (enableFundamentalAPI) { @@ -1086,7 +1103,7 @@ function commitUnmount( current.stateNode = null; } } - return; + break; } case DehydratedFragment: { if (enableSuspenseCallback) { @@ -1098,15 +1115,21 @@ function commitUnmount( } } } - return; + break; } case ScopeComponent: { if (enableScopeAPI) { safelyDetachRef(current, nearestMountedAncestor); } - return; + break; } } + + // Remove reference for GC + current.stateNode = null; + if (current.alternate != null) { + current.alternate.stateNode = null; + } } function commitNestedUnmounts( @@ -1460,6 +1483,8 @@ function unmountHostComponents( } if (node.tag === HostComponent || node.tag === HostText) { + // Save stateNode reference so commitUnmount can clear it. + const stateNode: Instance | TextInstance = node.stateNode; commitNestedUnmounts( finishedRoot, node, @@ -1469,15 +1494,9 @@ function unmountHostComponents( // After all the children have unmounted, it is now safe to remove the // node from the tree. if (currentParentIsContainer) { - removeChildFromContainer( - ((currentParent: any): Container), - (node.stateNode: Instance | TextInstance), - ); + removeChildFromContainer(((currentParent: any): Container), stateNode); } else { - removeChild( - ((currentParent: any): Instance), - (node.stateNode: Instance | TextInstance), - ); + removeChild(((currentParent: any): Instance), stateNode); } // Don't visit children because we already visited them. } else if (enableFundamentalAPI && node.tag === FundamentalComponent) { diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js index e094e5bd9b5a8..6ad605ca3698b 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js @@ -906,7 +906,7 @@ function commitUnmount( } while (effect !== firstEffect); } } - return; + break; } case ClassComponent: { safelyDetachRef(current); @@ -914,11 +914,28 @@ function commitUnmount( if (typeof instance.componentWillUnmount === 'function') { safelyCallComponentWillUnmount(current, instance); } - return; + break; } case HostComponent: { safelyDetachRef(current); - return; + // HACK: detach fiber references from DOM + current.stateNode.__reactFiber$ = null; + current.stateNode.__reactProps$ = null; + current.stateNode.__reactContainer$ = null; + current.stateNode.__reactEvents$ = null; + current.stateNode.__reactListeners$ = null; + current.stateNode.__reactHandles$ = null; + break; + } + case HostText: { + // HACK: detach fiber references from DOM + current.stateNode.__reactFiber$ = null; + current.stateNode.__reactProps$ = null; + current.stateNode.__reactContainer$ = null; + current.stateNode.__reactEvents$ = null; + current.stateNode.__reactListeners$ = null; + current.stateNode.__reactHandles$ = null; + break; } case HostPortal: { // TODO: this is recursive. @@ -929,7 +946,7 @@ function commitUnmount( } else if (supportsPersistence) { emptyPortalContainer(current); } - return; + break; } case FundamentalComponent: { if (enableFundamentalAPI) { @@ -939,7 +956,7 @@ function commitUnmount( current.stateNode = null; } } - return; + break; } case DehydratedFragment: { if (enableSuspenseCallback) { @@ -951,15 +968,21 @@ function commitUnmount( } } } - return; + break; } case ScopeComponent: { if (enableScopeAPI) { safelyDetachRef(current); } - return; + break; } } + + // Remove reference for GC + current.stateNode = null; + if (current.alternate != null) { + current.alternate.stateNode = null; + } } function commitNestedUnmounts( @@ -1314,19 +1337,15 @@ function unmountHostComponents( } if (node.tag === HostComponent || node.tag === HostText) { + // Save stateNode reference so commitUnmount can clear it. + const stateNode: Instance | TextInstance = node.stateNode; commitNestedUnmounts(finishedRoot, node, renderPriorityLevel); // After all the children have unmounted, it is now safe to remove the // node from the tree. if (currentParentIsContainer) { - removeChildFromContainer( - ((currentParent: any): Container), - (node.stateNode: Instance | TextInstance), - ); + removeChildFromContainer(((currentParent: any): Container), stateNode); } else { - removeChild( - ((currentParent: any): Instance), - (node.stateNode: Instance | TextInstance), - ); + removeChild(((currentParent: any): Instance), stateNode); } // Don't visit children because we already visited them. } else if (enableFundamentalAPI && node.tag === FundamentalComponent) {