Commit Graph

22 Commits

Author SHA1 Message Date
Sean Perkins
f14a59c5e0 fix(react): lifecycle events are removed on page unmount (#28316)
Issue number: N/A

---------

<!-- 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. -->

While debugging #28186, Maria and I identified that Ionic's lifecycle
event listeners (`ionViewWillEnter`, etc.) were being registered
multiple times on the same `.ion-page` element. This resulted in
problematic behavior, where a user's implementation of our lifecycle
hooks, would execute their callback multiple times.

```ts
useIonViewWillEnter(() => {
  // This is called 2x for every time the `ionViewWillEnter` event is emitted (in React 18, dev mode)
  console.log('hello world'); 
});
```

When the Ionic lifecycle event listeners are registered in React, we
bind the scope of the class to the callback function. When removing the
event listener we additional use the `.bind` syntax.

```tsx
componentDidMount() {
  element.addEventListener('ionViewWillEnter', this.ionViewWillEnter.bind(this));
} 

componentWillUnmount() {
  // This creates a new instance of the function to remove! It doesn't remove the original event listener.
  element.removeEventListener('ionViewWillEnter', this.ionViewWillEnter.bind(this)); 
}
```

The `.bind` method returns a new instance of the function. This means in
the implementation we are creating a new instance of the function when
both adding and removing the event listener - resulting in the
`removeEventListener` to never remove the original event listener.

This behavior only occurred in React 18 in dev mode, as a result of the
mount/unmount behavior running 2x for `useEffect` hooks.

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

- Ionic lifecycle event listeners are removed from element references
when they are unmounted.
- User's lifecycle callback methods are only invoked once per event
emission.

|Before|After|
|----|----|
|<img alt="CleanShot 2023-10-09 at 18 32 08@2x"
src="https://github.com/ionic-team/ionic-framework/assets/13732623/53f2ef5d-5900-4a84-b427-fa6c9d35d081">|<img
alt="CleanShot 2023-10-09 at 18 29 37@2x"
src="https://github.com/ionic-team/ionic-framework/assets/13732623/c8a9a657-a0bf-4d6d-9f21-a41a686de490">|


## 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. -->

---------

Co-authored-by: Maria Hutt <maria@ionic.io>
Co-authored-by: Amanda Johnston <90629384+amandaejohnston@users.noreply.github.com>
2023-10-12 15:02:21 +00:00
Liam DeBeasi
abcfe9fe86 fix(react): hardware back button works in dev mode (#26614)
resolves #26599
2023-01-19 10:49:47 -05:00
Liam DeBeasi
b02190d71f chore(react): migrate to eslint, add prettier (#26633) 2023-01-18 16:49:25 -05:00
Amanda Johnston
c2e1ad385d chore(many): replace any types and add tech debt tickets (#26293)
Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
2023-01-06 09:34:55 -06:00
Liam DeBeasi
a39d776f08 fix(react): duplicate page transitions do not happen on react 18 (#25798)
resolves #25797
2022-08-23 14:19:38 -04:00
Sean Perkins
3878bf7652 fix(react): outlet will not clear in react 18 with hot reload (#25703)
Resolves #25507
2022-08-03 16:33:26 -04:00
Liam DeBeasi
7ec3683e94 fix(react): swipe to go back gesture works on ios (#25563)
resolves #22342

Co-authored-by: masonicboom <masonicboom@users.noreply.github.com>
2022-07-19 09:28:10 -04:00
Sean Perkins
a296ca875c fix(react): treeshake ionic/core bundle (#24989)
Resolves #24497

Co-authored-by: mlegenhausen <mlegenhausen@mailbox.org>
2022-03-24 12:17:15 -04:00
Sean Perkins
43aa6c11f4 fix(react): nested router outlets will not reanimate entered views (#24672)
Resolves #24107
2022-01-31 11:55:08 -05:00
Liam DeBeasi
c50d895370 feat(react): add custom elements bundle (#23896) 2021-09-13 14:53:28 -04:00
William Martin
1680b0ce9f refactor(react): transition to Stencil React bindings (#23826) 2021-08-31 17:29:59 -04:00
William Martin
c501da73be fix(react): remove hardware back button event listener when NavManager is unmounted (#23224)
resolves #23170
2021-04-28 17:47:33 -04:00
Tucker Whitehouse
0dd189e2c0 fix(react): callback refs now work correctly with ionic components (#23152)
resolves #23153
2021-04-22 09:56:04 -04:00
Ely Lucas
f891f66708 fix(react): improve view matching logic (#22569) 2020-12-15 11:03:08 -05:00
Ely Lucas
a01bdb8c8d fix(react): adding dynamic class to ion-page no longer hides component (#22666)
resolves #22631
2020-12-15 11:02:06 -05:00
Ely Lucas
91aaaab71a chore(react): adding prettier and formating files 2020-12-07 09:31:33 -07:00
Ely Lucas
36939e10ae fix(react): android hardware button should invoke browser back 2020-12-07 08:33:00 -07:00
Ely Lucas
74af3cb50b fix(react): Keep a hold of previous routes when doing a redirect, closes #22053 2020-09-08 19:58:00 -06:00
Ely Lucas
b11e06cec1 fix(react): redirect routes should unmount leaving component, fixes #22022 (#22029) 2020-09-04 14:56:20 -06:00
Ely Lucas
a15cd01bc3 fix(react): fixes swipe to go back regression (#21791) 2020-07-21 22:30:44 -06:00
Ely Lucas
f4a08b7ed4 fix(react): fixng ion-router-outlet ref regresssion (#21786) 2020-07-21 08:48:25 -06:00
Ely Lucas
c171ccbd37 feat(react): React Router Enhancements (#21693) 2020-07-07 12:02:05 -05:00