/
githubmirror
/
ionic
Обзор
Документация
Войти
/
githubmirror
/
ionic
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/react/src/routing/OutletPageManager.tsx
110 строк
4 KB
Sean Perkins
fix(react): lifecycle events are removed on page unmount (#28316)
12 окт 2023, 18:02
Не верифицирован
12 окт 2023, 18:02
f14a59c
Код
Авторство
О чём код?
import { componentOnReady } from '@ionic/core/components'; import React from 'react'; import { IonRouterOutletInner } from '../components/inner-proxies'; import { IonLifeCycleContext } from '../contexts/IonLifeCycleContext'; import type { RouteInfo } from '../models'; import { StackContext } from './StackContext'; interface OutletPageManagerProps { className?: string; forwardedRef?: React.ForwardedRef<HTMLIonRouterOutletElement>; routeInfo?: RouteInfo; StackManager: any; // TODO(FW-2959): type } export class OutletPageManager extends React.Component<OutletPageManagerProps> { ionLifeCycleContext!: React.ContextType<typeof IonLifeCycleContext>; context!: React.ContextType<typeof StackContext>; ionRouterOutlet: HTMLIonRouterOutletElement | undefined; outletIsReady: boolean; constructor(props: OutletPageManagerProps) { super(props); this.outletIsReady = false; /** * This binds the scope of the following methods to the class scope. * The `.bind` method returns a new function, so we need to assign it * in the constructor rather than when adding or removing the listeners * to avoid creating a new function. */ this.ionViewWillEnterHandler = this.ionViewWillEnterHandler.bind(this); this.ionViewDidEnterHandler = this.ionViewDidEnterHandler.bind(this); this.ionViewWillLeaveHandler = this.ionViewWillLeaveHandler.bind(this); this.ionViewDidLeaveHandler = this.ionViewDidLeaveHandler.bind(this); } componentDidMount() { if (this.ionRouterOutlet) { /** * This avoids multiple raf calls * when React unmounts + remounts components. */ if (!this.outletIsReady) { componentOnReady(this.ionRouterOutlet, () => { this.outletIsReady = true; this.context.registerIonPage(this.ionRouterOutlet!, this.props.routeInfo!); }); } this.ionRouterOutlet.addEventListener('ionViewWillEnter', this.ionViewWillEnterHandler); this.ionRouterOutlet.addEventListener('ionViewDidEnter', this.ionViewDidEnterHandler); this.ionRouterOutlet.addEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler); this.ionRouterOutlet.addEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler); } } componentWillUnmount() { if (this.ionRouterOutlet) { this.ionRouterOutlet.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler); this.ionRouterOutlet.removeEventListener('ionViewDidEnter', this.ionViewDidEnterHandler); this.ionRouterOutlet.removeEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler); this.ionRouterOutlet.removeEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler); } } ionViewWillEnterHandler() { this.ionLifeCycleContext.ionViewWillEnter(); } ionViewDidEnterHandler() { this.ionLifeCycleContext.ionViewDidEnter(); } ionViewWillLeaveHandler() { this.ionLifeCycleContext.ionViewWillLeave(); } ionViewDidLeaveHandler() { this.ionLifeCycleContext.ionViewDidLeave(); } render() { const { StackManager, children, routeInfo, ...props } = this.props; return ( <IonLifeCycleContext.Consumer> {(context) => { this.ionLifeCycleContext = context; return ( <StackManager routeInfo={routeInfo}> <IonRouterOutletInner setRef={(val: HTMLIonRouterOutletElement) => (this.ionRouterOutlet = val)} {...props} > {children} </IonRouterOutletInner> </StackManager> ); }} </IonLifeCycleContext.Consumer> ); } static get contextType() { return StackContext; } } export default OutletPageManager;