-
Notifications
You must be signed in to change notification settings - Fork 13.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(react): inline overlays dismiss when parent component unmounts #26245
Conversation
Updated dev-build: |
Thinking about this approach a little more, if we do not like the filtering out of events to pass to |
Just checking in on this fix, could the team provide an update what is its status? |
I just tried out the dev build
In the current prod build I just discovered that code like above freezes the (inactive) modal over the whole screen. But with this dev build it automatically closes the modal as I would have hoped. |
@sean-perkins Bump? |
Open PRs are considered active work. There are a number of factors that effects our prioritization of different work items. This specific PR addresses behavior that has not been designed or documented by Ionic and is important that we spent time to thoroughly designing the expected behaviors internally, so we do not need to perform a breaking change to correct that behavior in the future. This PR has been updated to remove incorrect assumptions I had made in the first implementation pass, such as trying to perform the dismiss transition for the overlay when the parent component unmounts or a router action is performed. In these scenarios, we should be treating the overlay lifecycle as: graph TD
A[Overlay]--> Mounted
Mounted --> Presented
Presented --> Unmounted
In this diagram we show that the "Dismiss" lifecycle does not occur. This means that a dismiss transition is not performed and the respective events Here is an updated dev-build to test with: |
componentDidUpdate(prevProps: IonicReactInternalProps<PropType>) { | ||
const node = this.ref.current! as HTMLElement; | ||
attachProps(node, this.props, prevProps); | ||
node.removeEventListener('didDismiss', this.handleDidDismiss); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we only remove the didDismiss
event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The createInlineOverlayComponent
binds two internal event listeners for didDismiss
and willPresent
. Both implementations have an internal state update for:
this.setState({ isOpen: false }); // `true` for willPresent
At this point in the lifecycle of the component the component is unmounting. willPresent
cannot fire. However, didDismiss
can fire and cause any user-implemented callback handlers for onDidDismiss
to run after the React component has unmounted. If this occurs, React will throw an exception in the console about a memory leak.
This code disconnects the internal event listener manually, before the element can dispatch didDismiss
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would detachProps
handle removing that listener? If so, would it make sense to instead call detachProps
before node.remove
and then remove this line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
detachProps
only removes event listeners added by attachProps
(because we track the events on the element node on a key called __events
). This specific event listener is manually added within the React class and isn't removed as a result of detachProps
.
componentDidUpdate(prevProps: IonicReactInternalProps<PropType>) { | ||
const node = this.ref.current! as HTMLElement; | ||
attachProps(node, this.props, prevProps); | ||
node.removeEventListener('didDismiss', this.handleDidDismiss); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would detachProps
handle removing that listener? If so, would it make sense to instead call detachProps
before node.remove
and then remove this line?
Pull request checklist
Please check if your PR fulfills the following requirements:
ionic-docs
repo, in a separate PR. See the contributing guide for details.npm run build
) was run locally and any changes were pushednpm run lint
) has passed locally and any fixes were made for failuresPull request type
Please check the type of change your PR introduces:
What is the current behavior?
When navigation events occur (push, pop, replace), presented inline overlays are not unmounted from the DOM. Additionally, when a parent component is unmounted, presented overlays are not unmounted.
Issue URL: #25775, #26185
What is the new behavior?
willDismiss
ordidDismiss
events.willDismiss
ordidDismiss
events.Does this introduce a breaking change?
Other information
Dev-build:
6.5.4-dev.11676062329.117ad0d6
(updated 02/10/2023)