Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions BREAKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,32 @@ The `@ionic/react-router` package now requires React Router v6. React Router v5
| react-router | 6.4.0+ |
| react-router-dom | 6.4.0+ |

**TypeScript**

The `@ionic/react` package now requires TypeScript 5.4 or later. Its type definitions use `NoInfer`, which TypeScript added in 5.4. This matches the minimum that `@ionic/angular` already requires.

**Typed Overlay Hook Props**

The `useIonModal` and `useIonPopover` hooks type `componentProps` against the component they are given, instead of accepting `any`. Props that do not match the component are a compile error, and `componentProps` is required when the component declares required props. Applications passing incorrect props will see new type errors at build time rather than failing at runtime.

```diff
const Modal: React.FC<{ title: string }> = ({ title }) => <IonContent>{title}</IonContent>;

- const [present, dismiss] = useIonModal(Modal, { subtitle: 'Wrong' });
+ const [present, dismiss] = useIonModal(Modal, { title: 'Hello' });
```

Props are read from the component rather than from `componentProps`, so a component declared inline needs its props annotated:

```diff
- const [present, dismiss] = useIonModal(({ name }) => <div>Hello {name}.</div>, { name: 'Dave' });
+ const [present, dismiss] = useIonModal(({ name }: { name: string }) => <div>Hello {name}.</div>, { name: 'Dave' });
```

Passing a JSX element rather than a component is unchanged, and `componentProps` is not type checked in that case.

`npx @ionic/migrate` reports the calls this affects and names what is wrong with each, but does not rewrite them, since the right fix depends on what the call was meant to do. For the inline case above, `--experimental` can annotate the parameter from the `componentProps` object literal being passed.

React Router v6 introduces several API changes that will require updates to your application's routing configuration:

**Route Definition Changes**
Expand Down
3 changes: 3 additions & 0 deletions packages/migrate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ under [`docs/`](./docs).
- Only `.ts` and `.tsx` are loaded into `ts-morph`, so `.js`/`.jsx` files and
Angular inline templates (a `template:` string in a decorator) get the
text-scan migrations but not the AST-based ones.
- No `tsconfig.json` is read. The type checker gets a fixed configuration, so a
`paths` alias doesn't resolve, and a migration reading types treats what it
can't reach as unknown rather than as nothing to report.
- The template scanner is best-effort, not a full HTML parser.
- Stylesheet scanning covers `.css` and `.scss` files. Styles inlined in a
component decorator's `styles` array aren't read.
Expand Down
16 changes: 16 additions & 0 deletions packages/migrate/docs/v9.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ the whole list for a vanilla app.
| Change | Mode |
| --- | --- |
| `@ionic/react` + React 18 + React Router v6 bumps, drop `@types/react-router*` | auto |
| TypeScript raised to the 5.4 floor | auto |
| `<Route exact>` removal, `component={X}` -> `element={<X />}` | auto |
| React Router v6: removed imports, `IonRedirect`, `render`/non-identifier `component`, route children, `history` prop, regex paths | report |
| `useIonModal`/`useIonPopover` calls whose `componentProps` no longer type check | report |
| An inline overlay component's unannotated props parameter | experimental |

### Vue

Expand Down Expand Up @@ -81,13 +84,26 @@ The tool can't point at the code these changes affect, so check them against the
in an Ionic lifecycle hook stops re-rendering. The report flags Angular 22 in
`package.json`, but it doesn't find the affected components - `ng update` has a
migration for that.
- Overlay hook calls whose component the type checker can't resolve. The tool
runs without your `tsconfig.json`, so a component behind a `paths` alias
(`@/components/Modal`), or one typed as `React.FC` with `@types/react`
uninstalled, is skipped rather than guessed at, and a build error can still be
waiting in one. A mismatch that only exists under `strict` is skipped too, so
that everything it does report is a real error.

## Notes on individual migrations

- Angular zoneless is auto-fixed only for the standalone `bootstrapApplication`
shape. NgModule apps are flagged for manual migration instead. Neither fires
unless the app loads Zone.js, since there is nothing to preserve otherwise and
the provider fails to bootstrap without it.
- The overlay hook prop changes are report-only: a prop the component doesn't
declare is either a typo or a prop it should have declared, and a missing
required prop has no value to supply. The exception is a component written
inline at the call, whose props parameter `--experimental` annotates from the
`componentProps` object literal it is passed. That is a guess at intent
(`{ name: 'Dave' }` gives `{ name: string }`), and it declines anything but a
literal, or props that don't cover every name the component reads.
- The component DOM/shadow-part changes are report-only. The right replacement
depends on what the CSS rule was doing, and `ion-select`'s `part="inner"` has
none at all.
Expand Down
Loading