fix(react): present controller overlays in React 18 (#25361)

Resolves #25247
This commit is contained in:
Sean Perkins
2022-05-31 09:57:27 -04:00
committed by GitHub
parent 982909017b
commit 01c40eae55

View File

@ -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();
}
}