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>
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>
Issue number: resolves#27911
---------
<!-- 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. -->
The `openURL` utility is not available to developers.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- Export `openURL` utilities from `@ionic/core`, `@ionic/angular`,
`@ionic/react` and `@ionic/vue`.
## 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. -->
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. -->
CI is failing for Cypress apps due to
https://github.com/cypress-io/cypress/issues/27804#issuecomment-1721476731.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- All Cypress test apps have been updated to Cypress 13.2.0 which is not
affected by this issue.
## 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. -->
Issue number: Resolves#27798
---------
## What is the current behavior
React IonNav component's views are missing keys, leading to unnecessary
duplicate mounting of components.
## What is the new behavior?
- Adds key to views of React IonNav component.
## Does this introduce a breaking change?
- [ ] Yes
- [x] No
---------
Co-authored-by: Sean Perkins <sean@ionic.io>
Issue number: resolves#28137
---------
Changes according to [this
comment](https://github.com/ionic-team/ionic-framework/issues/28137#issuecomment-1710283096)
## Does this introduce a breaking change?
- [ ] Yes
- [x] No
@liamdebeasi Sorry for replacing the previous PR. I only copied the main
branch to my fork so I couldn't rebase properly. I am unfortunately not
extremely familiar with Github.
---------
Co-authored-by: Philipp Heuer <philipp@studysmarter.de>
Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
Issue number: resolves#28102
---------
<!-- 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. -->
When one modal is added and another modal is removed, the modal that is
removed does not account for the newly added modal when updating the
overlay context in React. As a result, the inner contents of the newly
added modal is not mounted.
We originally tried to fix this in
https://github.com/ionic-team/ionic-framework/pull/24553, but the fix
was not complete. While storing the latest information in a React ref
was correct, the way we updated the ref was done in a way such that data
was still stale.
In particular, the `overlaysRef` is updated whenever `IonOverlayManager`
is re-rendered. State updates are batched, so updating the state twice
in quick succession does not necessarily result in 2 separate renders.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- We need to make sure the ref is updated synchronously before any
render so that `addOverlay` and `removeOverlay` always have access to
the latest data.
- Added a test
## 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.3.3-dev.11693592339.18e000af`
---------
Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com>
Co-authored-by: Amanda Johnston <90629384+amandaejohnston@users.noreply.github.com>
Issue number: Resolves#28010
---------
<!-- 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. -->
`onDidDismiss` and `onWillPresent` will fire twice when having a manual
binding in your implementation for inline overlays.
e.g.:
```tsx
<IonAlert onDidDismiss={() => console.log('hello world')} />
```
Will result in:
> hello world
> hello world
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- `onDidDismiss` and `onWillPresent` do not execute the callback handler
twice per invocation
## 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.3.1-dev.11692305436.16a4008f`
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. -->
The sync script for the React package is out of date. It will
unintentionally delete the symlink directory of the build output from
`core/`, which breaks the build for the package during local
development.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- Updates the sync script to package and install the `core` package
- Matches the implementation pattern used for the sync script in our
other packages
## 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. -->
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. -->
React 17/18 test apps use react-scripts. This does not align with our
starter templates.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- Updates the React 18 test app to use Vite
- Leaves the React 17 test app on react-scripts for now
- Updates test app dependencies to align with the react starters
## 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. -->
closes#27949
---------
<!-- 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. -->
- Typescript is complaining about the `onClick` event type of the
`IonTabButton`
```ts
const App: React.FC = () => {
async function handleTabClick(e: CustomEvent<HTMLIonTabButtonElement>) {
alert(e.detail.tab);
}
return (
<IonTabButton tab="myTab" onClick={handleTabClick}>
);
};
```
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- `onClick` handler uses `CustomEvent` type
- Typescript does not error
## 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. -->