mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 02:31:34 +08:00
fix(react): present controller overlays in React 18 (#25361)
Resolves #25247
This commit is contained in:
@ -1,7 +1,12 @@
|
||||
import { OverlayEventDetail } from '@ionic/core/components';
|
||||
import React from 'react';
|
||||
|
||||
import { attachProps, dashToPascalCase, defineCustomElement, setRef } from './react-component-lib/utils';
|
||||
import {
|
||||
attachProps,
|
||||
dashToPascalCase,
|
||||
defineCustomElement,
|
||||
setRef,
|
||||
} from './react-component-lib/utils';
|
||||
|
||||
interface OverlayBase extends HTMLElement {
|
||||
present: () => Promise<void>;
|
||||
@ -39,7 +44,7 @@ export const createControllerComponent = <
|
||||
|
||||
class Overlay extends React.Component<Props> {
|
||||
overlay?: OverlayType;
|
||||
isUnmounted = false;
|
||||
willUnmount = false;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
@ -51,6 +56,14 @@ export const createControllerComponent = <
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
/**
|
||||
* Starting in React v18, strict mode will unmount and remount a component.
|
||||
* See: https://reactjs.org/blog/2022/03/29/react-v18.html#new-strict-mode-behaviors
|
||||
*
|
||||
* We need to reset this flag when the component is re-mounted so that
|
||||
* overlay.present() will be called and the overlay will display.
|
||||
*/
|
||||
this.willUnmount = false;
|
||||
const { isOpen } = this.props;
|
||||
if (isOpen as boolean) {
|
||||
this.present();
|
||||
@ -58,7 +71,7 @@ export const createControllerComponent = <
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.isUnmounted = true;
|
||||
this.willUnmount = true;
|
||||
if (this.overlay) {
|
||||
this.overlay.dismiss();
|
||||
}
|
||||
@ -77,18 +90,17 @@ export const createControllerComponent = <
|
||||
if (this.props.onDidDismiss) {
|
||||
this.props.onDidDismiss(event);
|
||||
}
|
||||
setRef(this.props.forwardedRef, null)
|
||||
setRef(this.props.forwardedRef, null);
|
||||
}
|
||||
|
||||
async present(prevProps?: Props) {
|
||||
const {
|
||||
isOpen,
|
||||
onDidDismiss,
|
||||
onDidPresent,
|
||||
onWillDismiss,
|
||||
onWillPresent,
|
||||
...cProps
|
||||
} = this.props;
|
||||
const { isOpen, onDidDismiss, onDidPresent, onWillDismiss, onWillPresent, ...cProps } =
|
||||
this.props;
|
||||
|
||||
if (this.overlay) {
|
||||
this.overlay.remove();
|
||||
}
|
||||
|
||||
this.overlay = await controller.create({
|
||||
...(cProps as any),
|
||||
});
|
||||
@ -107,8 +119,8 @@ export const createControllerComponent = <
|
||||
);
|
||||
// Check isOpen again since the value could have changed during the async call to controller.create
|
||||
// It's also possible for the component to have become unmounted.
|
||||
if (this.props.isOpen === true && this.isUnmounted === false) {
|
||||
setRef(this.props.forwardedRef, this.overlay)
|
||||
if (this.props.isOpen === true && this.willUnmount === false) {
|
||||
setRef(this.props.forwardedRef, this.overlay);
|
||||
await this.overlay.present();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user