Files
Sean Perkins 1ba9973857 fix(react): cleanup functions are execute for lifecycle hooks (#28319)
Issue number: Resolves #28186

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Ionic lifecycle hooks do not execute a cleanup function when the
underlying `useEffect` is unmounted.

```ts
useEffect(() => {
  return () => {
     console.log('cleanup'); // called
   };
});

useIonViewWillEnter(() => {
  return () => {
     console.log('cleanup'); // never called
  };
});
```

Ionic's implementation registers the lifecycle callback to be handled at
a later time, by the page managers. However, it does not keep a
reference to the returned callback, so it cannot execute it when the
`useEffect` is unmounted.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Ionic lifecycle hooks execute dev-specified cleanup functions

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev-build: `7.4.4-dev.11696956070.1faa3cfe`

This PR builds on the changes in #28316.

---------

Co-authored-by: Maria Hutt <maria@ionic.io>
Co-authored-by: Amanda Johnston <90629384+amandaejohnston@users.noreply.github.com>
2023-10-12 19:19:01 +00:00

57 lines
1.9 KiB
TypeScript

import { useContext, useEffect, useRef } from 'react';
import type { LifeCycleCallback } from '../contexts/IonLifeCycleContext';
import { IonLifeCycleContext } from '../contexts/IonLifeCycleContext';
export const useIonViewWillEnter = (callback: LifeCycleCallback, deps: any[] = []) => {
const context = useContext(IonLifeCycleContext);
const id = useRef<number | undefined>();
id.current = id.current || Math.floor(Math.random() * 1000000);
useEffect(() => {
callback.id = id.current!;
context.onIonViewWillEnter(callback);
return () => {
context.cleanupIonViewWillEnter(callback);
};
}, deps);
};
export const useIonViewDidEnter = (callback: LifeCycleCallback, deps: any[] = []) => {
const context = useContext(IonLifeCycleContext);
const id = useRef<number | undefined>();
id.current = id.current || Math.floor(Math.random() * 1000000);
useEffect(() => {
callback.id = id.current!;
context.onIonViewDidEnter(callback);
return () => {
context.cleanupIonViewDidEnter(callback);
};
}, deps);
};
export const useIonViewWillLeave = (callback: LifeCycleCallback, deps: any[] = []) => {
const context = useContext(IonLifeCycleContext);
const id = useRef<number | undefined>();
id.current = id.current || Math.floor(Math.random() * 1000000);
useEffect(() => {
callback.id = id.current!;
context.onIonViewWillLeave(callback);
return () => {
context.cleanupIonViewWillLeave(callback);
};
}, deps);
};
export const useIonViewDidLeave = (callback: LifeCycleCallback, deps: any[] = []) => {
const context = useContext(IonLifeCycleContext);
const id = useRef<number | undefined>();
id.current = id.current || Math.floor(Math.random() * 1000000);
useEffect(() => {
callback.id = id.current!;
context.onIonViewDidLeave(callback);
return () => {
context.cleanupIonViewDidLeave(callback);
};
}, deps);
};