mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +08:00
fix(react): overlay hooks memorised properly to prevent re-renders (#24010)
resolves #23741 Co-authored-by: Fabrice <fabrice@weinberg.me>
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import { OverlayEventDetail } from '@ionic/core';
|
||||
import { useMemo, useRef } from 'react';
|
||||
import { useCallback, useMemo, useRef } from 'react';
|
||||
|
||||
import { attachProps } from '../components/utils';
|
||||
|
||||
@ -10,71 +10,53 @@ interface OverlayBase extends HTMLElement {
|
||||
dismiss: (data?: any, role?: string | undefined) => Promise<boolean>;
|
||||
}
|
||||
|
||||
export function useController<
|
||||
OptionsType,
|
||||
OverlayType extends OverlayBase
|
||||
>(
|
||||
export function useController<OptionsType, OverlayType extends OverlayBase>(
|
||||
displayName: string,
|
||||
controller: { create: (options: OptionsType) => Promise<OverlayType> }
|
||||
) {
|
||||
const overlayRef = useRef<OverlayType>();
|
||||
const didDismissEventName = useMemo(
|
||||
() => `on${displayName}DidDismiss`,
|
||||
[displayName]
|
||||
);
|
||||
const didPresentEventName = useMemo(
|
||||
() => `on${displayName}DidPresent`,
|
||||
[displayName]
|
||||
);
|
||||
const willDismissEventName = useMemo(
|
||||
() => `on${displayName}WillDismiss`,
|
||||
[displayName]
|
||||
);
|
||||
const willPresentEventName = useMemo(
|
||||
() => `on${displayName}WillPresent`,
|
||||
[displayName]
|
||||
);
|
||||
const didDismissEventName = useMemo(() => `on${displayName}DidDismiss`, [displayName]);
|
||||
const didPresentEventName = useMemo(() => `on${displayName}DidPresent`, [displayName]);
|
||||
const willDismissEventName = useMemo(() => `on${displayName}WillDismiss`, [displayName]);
|
||||
const willPresentEventName = useMemo(() => `on${displayName}WillPresent`, [displayName]);
|
||||
|
||||
const present = async (options: OptionsType & HookOverlayOptions) => {
|
||||
if (overlayRef.current) {
|
||||
return;
|
||||
}
|
||||
const {
|
||||
onDidDismiss,
|
||||
onWillDismiss,
|
||||
onDidPresent,
|
||||
onWillPresent,
|
||||
...rest
|
||||
} = options;
|
||||
|
||||
const handleDismiss = (event: CustomEvent<OverlayEventDetail<any>>) => {
|
||||
if (onDidDismiss) {
|
||||
onDidDismiss(event);
|
||||
const present = useCallback(
|
||||
async (options: OptionsType & HookOverlayOptions) => {
|
||||
if (overlayRef.current) {
|
||||
return;
|
||||
}
|
||||
const { onDidDismiss, onWillDismiss, onDidPresent, onWillPresent, ...rest } = options;
|
||||
|
||||
const handleDismiss = (event: CustomEvent<OverlayEventDetail<any>>) => {
|
||||
if (onDidDismiss) {
|
||||
onDidDismiss(event);
|
||||
}
|
||||
overlayRef.current = undefined;
|
||||
};
|
||||
|
||||
overlayRef.current = await controller.create({
|
||||
...(rest as any),
|
||||
});
|
||||
|
||||
attachProps(overlayRef.current, {
|
||||
[didDismissEventName]: handleDismiss,
|
||||
[didPresentEventName]: (e: CustomEvent) => onDidPresent && onDidPresent(e),
|
||||
[willDismissEventName]: (e: CustomEvent) => onWillDismiss && onWillDismiss(e),
|
||||
[willPresentEventName]: (e: CustomEvent) => onWillPresent && onWillPresent(e),
|
||||
});
|
||||
|
||||
overlayRef.current.present();
|
||||
},
|
||||
[controller]
|
||||
);
|
||||
|
||||
const dismiss = useCallback(
|
||||
() => async () => {
|
||||
overlayRef.current && (await overlayRef.current.dismiss());
|
||||
overlayRef.current = undefined;
|
||||
}
|
||||
|
||||
overlayRef.current = await controller.create({
|
||||
...(rest as any),
|
||||
});
|
||||
|
||||
attachProps(overlayRef.current, {
|
||||
[didDismissEventName]: handleDismiss,
|
||||
[didPresentEventName]: (e: CustomEvent) =>
|
||||
onDidPresent && onDidPresent(e),
|
||||
[willDismissEventName]: (e: CustomEvent) =>
|
||||
onWillDismiss && onWillDismiss(e),
|
||||
[willPresentEventName]: (e: CustomEvent) =>
|
||||
onWillPresent && onWillPresent(e),
|
||||
});
|
||||
|
||||
overlayRef.current.present();
|
||||
};
|
||||
|
||||
const dismiss = async () => {
|
||||
overlayRef.current && await overlayRef.current.dismiss();
|
||||
overlayRef.current = undefined;
|
||||
};
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return {
|
||||
present,
|
||||
|
Reference in New Issue
Block a user