Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1fecba9

Browse files
authored
Fix crash unmounting an empty Portal (facebook#14820)
* Adds failing test for facebook#14811 * Fix removeChild() crash when removing an empty Portal
1 parent e15542e commit 1fecba9

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

packages/react-dom/src/__tests__/ReactDOMFiber-test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,40 @@ describe('ReactDOMFiber', () => {
461461
expect(container.innerHTML).toBe('<div></div>');
462462
});
463463

464+
it('should unmount empty portal component wherever it appears', () => {
465+
const portalContainer = document.createElement('div');
466+
467+
class Wrapper extends React.Component {
468+
constructor(props) {
469+
super(props);
470+
this.state = {
471+
show: true,
472+
};
473+
}
474+
render() {
475+
return (
476+
<div>
477+
{this.state.show && (
478+
<React.Fragment>
479+
{ReactDOM.createPortal(null, portalContainer)}
480+
<div>child</div>
481+
</React.Fragment>
482+
)}
483+
<div>parent</div>
484+
</div>
485+
);
486+
}
487+
}
488+
489+
const instance = ReactDOM.render(<Wrapper />, container);
490+
expect(container.innerHTML).toBe(
491+
'<div><div>child</div><div>parent</div></div>',
492+
);
493+
instance.setState({show: false});
494+
expect(instance.state.show).toBe(false);
495+
expect(container.innerHTML).toBe('<div><div>parent</div></div>');
496+
});
497+
464498
it('should keep track of namespace across portals (simple)', () => {
465499
assertNamespacesMatch(
466500
<svg {...expectSVG}>

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,12 +1038,12 @@ function unmountHostComponents(current): void {
10381038
}
10391039
// Don't visit children because we already visited them.
10401040
} else if (node.tag === HostPortal) {
1041-
// When we go into a portal, it becomes the parent to remove from.
1042-
// We will reassign it back when we pop the portal on the way up.
1043-
currentParent = node.stateNode.containerInfo;
1044-
currentParentIsContainer = true;
1045-
// Visit children because portals might contain host components.
10461041
if (node.child !== null) {
1042+
// When we go into a portal, it becomes the parent to remove from.
1043+
// We will reassign it back when we pop the portal on the way up.
1044+
currentParent = node.stateNode.containerInfo;
1045+
currentParentIsContainer = true;
1046+
// Visit children because portals might contain host components.
10471047
node.child.return = node;
10481048
node = node.child;
10491049
continue;

0 commit comments

Comments
 (0)