diff --git a/UNRELEASED.md b/UNRELEASED.md index ea91b1bdc80..14b2a598a6f 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -15,6 +15,7 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f - Fixed tabs that don't wrap correctly on small screens in pre-iOS 13 Safari ([#2232](https://github.com/Shopify/polaris-react/pull/2232)) - Fixed `BulkActions` checkbox losing on selection focus ([#2138](https://github.com/Shopify/polaris-react/pull/2138)) - Moved rendering of the portal component’s node within the node created by the theme provider component to enable theming through CSS Custom Properties ([#2224](https://github.com/Shopify/polaris-react/pull/2224)) +- Fixed bug which caused the `Popover` overlay to remain in the DOM if it was updated during exiting ([#2246](https://github.com/Shopify/polaris-react/pull/2246)) ### Documentation diff --git a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx index 2ff8b59f766..b88e2d10d98 100644 --- a/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx +++ b/src/components/Popover/components/PopoverOverlay/PopoverOverlay.tsx @@ -85,11 +85,10 @@ export class PopoverOverlay extends React.PureComponent< } componentDidUpdate(oldProps: PopoverOverlayProps) { - this.clearTransitionTimeout(); - if (this.props.active && !oldProps.active) { this.focusContent(); this.changeTransitionStatus(TransitionStatus.Entering, () => { + this.clearTransitionTimeout(); this.enteringTimer = window.setTimeout(() => { this.setState({transitionStatus: TransitionStatus.Entered}); }, durationBase); @@ -98,6 +97,7 @@ export class PopoverOverlay extends React.PureComponent< if (!this.props.active && oldProps.active) { this.changeTransitionStatus(TransitionStatus.Exiting, () => { + this.clearTransitionTimeout(); this.exitingTimer = window.setTimeout(() => { this.setState({transitionStatus: TransitionStatus.Exited}); }, durationBase); diff --git a/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx b/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx index 75f859f3f41..95c173ca6e7 100644 --- a/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx +++ b/src/components/Popover/components/PopoverOverlay/tests/PopoverOverlay.test.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import {ReactWrapper} from 'enzyme'; import {mountWithAppProvider} from 'test-utilities/legacy'; import {TextContainer} from 'components'; import {Key} from '../../../../../types'; @@ -174,6 +175,43 @@ describe('', () => { /PopoverOverlay-entering/, ); }); + + it('does not render after exiting when the component is updated during exit', () => { + jest.useFakeTimers(); + + const popoverOverlay = mountWithAppProvider( + + {children} + , + ); + + // Start exiting + close(popoverOverlay); + + // Update before exiting is complete + triggerSomeUpdate(popoverOverlay); + + // Run any timers and a final update for changed state + jest.runOnlyPendingTimers(); + popoverOverlay.update(); + + expect(popoverOverlay.find(PositionedOverlay)).toHaveLength(0); + }); }); function noop() {} + +function close(wrapper: ReactWrapper) { + wrapper.setProps({active: false}); + wrapper.update(); +} + +function triggerSomeUpdate(wrapper: ReactWrapper) { + wrapper.setProps({fullWidth: true}); + wrapper.update(); +}