Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
4262324
chore(deps): update react router to v6
thetaPC May 8, 2025
f0127bd
refactor(utils): update matchPath for rr6
thetaPC May 8, 2025
cccf290
refactor(reactrouterviewstack): update for rr6 and improvements
thetaPC May 8, 2025
af7710b
refactor(test): updated test pages
thetaPC May 12, 2025
e364fea
chore(matchPath): use the correct library
thetaPC May 19, 2025
6a42e69
chore(rr6): run lint
thetaPC May 19, 2025
4aad76a
chore(StackManager): upgrade to rr6 and add comments
thetaPC May 19, 2025
fd6baac
chore(StackManager): more upgrades for rr6
thetaPC May 19, 2025
e76c1e8
docs(StackManager): update comment
thetaPC May 19, 2025
2436ba3
docs(matchPath): remove comment
thetaPC May 19, 2025
ca27ed6
chore(IonRouteInner): upgrade to rr6
thetaPC May 20, 2025
37f76c7
chore(StackManager): run lint
thetaPC Jun 9, 2025
a78f6b3
feat(IonRouter): migrate to functional component with react router 6
thetaPC Jun 9, 2025
93202c0
chore(IonRouteInner): update render
thetaPC Jun 9, 2025
0008059
docs(IonRouter, ReactRouterViewStack, StackManager): update comments
thetaPC Jun 9, 2025
0a0dcb6
feat(IonReactRouter): migrate to a functional component and react rou…
thetaPC Jun 11, 2025
331b394
feat(IonReactMemoryRouter): migrate to a functional component and rea…
thetaPC Jun 12, 2025
205a705
chore(IonReactMemoryRouter): remove unused type
thetaPC Jun 12, 2025
7ff8994
feat(IonReactHashRouter): migrate to a functional component and react…
thetaPC Jun 12, 2025
c45c0f9
docs(many): update comments
thetaPC Jun 13, 2025
12c49f5
refactor(many): remove `exact` from test pages
thetaPC Jun 13, 2025
71fb8cb
refactor(many): update to use <Navigate>
thetaPC Jun 13, 2025
c6f8dd4
refactor(many): replace `render` with `element`
thetaPC Jun 13, 2025
366004e
refactor(Tabs2): switch to navigate
thetaPC Jun 13, 2025
5cccf0b
refactor(many): update to prevent compile errors
thetaPC Jun 13, 2025
e6e17eb
refactor(IonReactRouter): split component to use hooks correctly
thetaPC Jun 13, 2025
2656e98
chore: update package and sync file
thetaPC Jun 13, 2025
10bb889
docs(IonReactRouter): use updated param names
thetaPC Jun 16, 2025
7a20697
fix(ReactRouterViewStack, StackManager): use correct value & add valu…
thetaPC Jun 17, 2025
9d69a69
Merge branch 'main' of github.com:ionic-team/ionic-framework into mh/…
thetaPC Jun 17, 2025
9c5f55a
test(rr5): keep the old pages
thetaPC Jun 18, 2025
49cbc46
test(dynamic-ionpage-classnames): use old version for rr5
thetaPC Jun 19, 2025
a926134
chore(rr5, rr6): update package
thetaPC Jun 20, 2025
a65886b
test(app, routing): use index
thetaPC Jun 21, 2025
51933fe
Merge branch 'main' of github.com:ionic-team/ionic-framework into mh/…
ShaneK Jul 11, 2025
43e546b
Merge branch 'main' of github.com:ionic-team/ionic-framework into mh/…
ShaneK Jul 16, 2025
fca5e6c
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Jul 17, 2025
80ae239
WIP
ShaneK Jul 21, 2025
c8cefd5
WIP
ShaneK Jul 24, 2025
b0c95d4
merge
ShaneK Jul 31, 2025
662fd70
WIP
ShaneK Aug 4, 2025
210bc16
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Aug 5, 2025
6f7631d
feat(react-router): have navigation in the routing page generally wor…
ShaneK Aug 6, 2025
6f72bbf
feat(react-router): adding support for route params
ShaneK Aug 11, 2025
0949a87
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Oct 8, 2025
8fd53b2
fix(react-router): addressing some migration issues with memory and h…
ShaneK Oct 8, 2025
0ceee27
fix(react-router): improving navigation stack reliability
ShaneK Oct 8, 2025
a6131ba
fix(react-router): improving matching with wildcard and parameter routes
ShaneK Oct 11, 2025
8035c82
fix(react-router): fixing redirect for test app so it uses replace ro…
ShaneK Oct 11, 2025
a9a1de2
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Oct 16, 2025
e293cc0
chore(test): adding text in refs test for people manually testing
ShaneK Oct 20, 2025
99436a3
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Oct 20, 2025
33fc844
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Oct 23, 2025
28ca3a7
fix(react-router): adding support for nested parameter access
ShaneK Oct 25, 2025
0d83b77
fix(react-router): skip IonPage wait for Navigate, adding documentati…
ShaneK Oct 26, 2025
054220d
trying to fix redirect
ShaneK Oct 28, 2025
1ed61a9
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Oct 30, 2025
8dddf77
fix(react-router): fixing dynamic tab and nested outlet tests so they…
ShaneK Oct 30, 2025
5b735cd
fix(router): correct relative base and param reuse
ShaneK Oct 30, 2025
881068e
Fixing test app tabs views
ShaneK Nov 7, 2025
6cae9ad
fix(react-router): trying to better handle nested routing
ShaneK Nov 20, 2025
763621d
fix(react-router): prevent unmounted Navigate components from trigger…
ShaneK Nov 21, 2025
d51f95e
fix(react-router): use state to track IonRouterOutlet ref id in test
ShaneK Nov 21, 2025
59f2dbf
fix(react): automatically dismiss inline overlays on navigation
ShaneK Nov 21, 2025
96c96fc
fix(react-router): add wildcard to refs route for nested routing
ShaneK Nov 21, 2025
383ec04
chore(status): updating status file
ShaneK Nov 22, 2025
10c31ed
chore(react-router): improving continuous testability
ShaneK Nov 24, 2025
045b0a7
fix(react-router): correct tab and nested outlet navigation
ShaneK Nov 24, 2025
3073a24
fix(react-router): fixing relative paths in tab context tests
ShaneK Nov 24, 2025
584dcf2
fix(react-router): prioritize specific route matches
ShaneK Nov 25, 2025
b02c197
fix(react-router): prevent incorrect view reuse for parameterized routes
ShaneK Nov 26, 2025
7fd0659
fix(react-router): nested redirect fix
ShaneK Nov 26, 2025
fc6e482
chore(react-router): cleaning up console logs
ShaneK Nov 26, 2025
6575a92
chore(react-router): removing rr5 test app since it will no longer be…
ShaneK Nov 26, 2025
fbed1e0
chore(react-router): fixing types, removing usued variable
ShaneK Nov 26, 2025
8fbd2d4
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Nov 26, 2025
3912623
fix(react-router): hide deactivated catch-all routes
ShaneK Nov 26, 2025
00798d4
fix(react-router): adding legacy peer dep flag during installation to…
ShaneK Nov 29, 2025
82fd1ba
fix(react-router): fixing views not being cleaned up properly, causin…
ShaneK Dec 1, 2025
5a77916
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Dec 1, 2025
397b6f7
chore(react-router): code clean up
ShaneK Dec 2, 2025
71e55ad
chore(react-router): refactor
ShaneK Dec 2, 2025
418ac75
chore(react-router): cleaning up util files
ShaneK Dec 2, 2025
99dcb35
chore(react-router): minor clean up
ShaneK Dec 2, 2025
a23f555
fix(react): fixing inline overlays being a bit eager to dismiss
ShaneK Dec 3, 2025
a565a37
fix(overlays): removing old band-aid code
ShaneK Dec 3, 2025
cb94f73
chore(docs): removing status doc link
ShaneK Dec 4, 2025
fedca46
fix(react-router): preserve nested outlet params when navigating betw…
ShaneK Dec 4, 2025
b2a7105
chore(react-router): adding migration details to BREAKING.md
ShaneK Dec 4, 2025
7fc43b6
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Dec 9, 2025
6762e5b
fix(react-router): isolate tab history to prevent cross-tab back navi…
ShaneK Dec 10, 2025
b196665
Merge branch 'main' of github.com:ionic-team/ionic-framework into sk/…
ShaneK Dec 10, 2025
2ff49c4
Merge branch 'major-9.0' of github.com:ionic-team/ionic-framework int…
ShaneK Dec 10, 2025
c283319
fix(react-router): isolate tab history to prevent cross-tab back navi…
ShaneK Dec 10, 2025
6a61ecf
chore(git): merge conflict resolution
ShaneK Dec 10, 2025
07104c2
fix(react-router): support React Router 6 style relative paths in Ion…
ShaneK Dec 16, 2025
e1e7a2e
fix(react-router): moving view stack back to generate ID
ShaneK Dec 17, 2025
d0451ed
chore(react-router): lots of comments, code clean up, comment clean u…
ShaneK Dec 17, 2025
6f184e5
refactor(react-router): extract helper functions from computeParentPath
ShaneK Dec 17, 2025
d44fc11
refactor(react-router): extract helper functions from render callback
ShaneK Dec 17, 2025
289f6ed
chore(react-router): documentation, comment clean up, and more
ShaneK Dec 17, 2025
ab3dde2
fix(react-router): cleanup orphaned sibling views after replace navig…
ShaneK Dec 17, 2025
ffa2e06
fix(react-router): prevent menu button flicker during non-animated pa…
ShaneK Dec 18, 2025
4fa0260
fix(react): preserve framework classes when IonPage className prop ch…
ShaneK Dec 18, 2025
8052ea1
test(react-router): fix test for nested outlet rendering on direct na…
ShaneK Dec 18, 2025
1e2bebb
fix(react-router): cleanup sibling views on push navigation to contai…
ShaneK Dec 18, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ jobs:
strategy:
fail-fast: false
matrix:
apps: [reactrouter5]
apps: [reactrouter6]
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stencil-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ jobs:
strategy:
fail-fast: false
matrix:
apps: [reactrouter5]
apps: [reactrouter6]
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
Expand Down
301 changes: 52 additions & 249 deletions BREAKING.md

Large diffs are not rendered by default.

282 changes: 282 additions & 0 deletions BREAKING_ARCHIVE/v8.md

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5,535 changes: 1,864 additions & 3,671 deletions packages/react-router/package-lock.json

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions packages/react-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"peerDependencies": {
"react": ">=16.8.6",
"react-dom": ">=16.8.6",
"react-router": "^5.0.1",
"react-router-dom": "^5.0.1"
"react-router": ">=6.0.0",
"react-router-dom": ">=6.0.0"
},
"devDependencies": {
"@ionic/eslint-config": "^0.3.0",
Expand All @@ -52,16 +52,15 @@
"@types/node": "^14.0.14",
"@types/react": "^17.0.79",
"@types/react-dom": "^17.0.25",
"@types/react-router": "^5.0.3",
"@types/react-router-dom": "^5.1.5",
"history": "^5.3.0",
"@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2",
"eslint": "^7.32.0",
"prettier": "^2.8.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router": "^5.0.1",
"react-router-dom": "^5.0.1",
"react-router": "^6.30.0",
"react-router-dom": "^6.30.0",
"rimraf": "^3.0.2",
"rollup": "^4.2.0",
"typescript": "^4.0.5"
Expand Down
22 changes: 11 additions & 11 deletions packages/react-router/scripts/sync.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

set -e

# Copy ionic react dist
rm -rf node_modules/@ionic/react/dist node_modules/@ionic/react/css
cp -a ../react/dist node_modules/@ionic/react/dist
cp -a ../react/css node_modules/@ionic/react/css
cp -a ../react/package.json node_modules/@ionic/react/package.json

# Copy core dist
rm -rf node_modules/@ionic/core/dist node_modules/@ionic/core/components
cp -a ../../core/dist node_modules/@ionic/core/dist
cp -a ../../core/components node_modules/@ionic/core/components
cp -a ../../core/package.json node_modules/@ionic/core/package.json
# Delete old packages
rm -f *.tgz

# Pack @ionic/react
npm pack ../react

# Pack @ionic/core
npm pack ../../core

# Install Dependencies
npm install *.tgz --no-save
68 changes: 68 additions & 0 deletions packages/react-router/scripts/test_runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/bash
set -x

# Change to script's directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

# Inside core
echo "Building core..."
cd ../../../core
npm run build

# Inside packages/react
echo "Building packages/react..."
cd ../packages/react
npm ci
npm run sync
npm run build

# Inside packages/react-router
echo "Building packages/react-router..."
cd ../react-router
npm ci
npm run sync
npm run build

# Inside packages/react-router/test
echo "Building test app..."
cd ./test
rm -rf build/reactrouter6 || true
sh ./build.sh reactrouter6
cd build/reactrouter6
echo "Installing dependencies..."
npm install --legacy-peer-deps > npm_install.log 2>&1
npm run sync

echo "Cleaning up port 3000..."
lsof -ti:3000 | xargs kill -9 || true

echo "Starting server..."
# Start server in background and save PID
npm start > server.log 2>&1 &
SERVER_PID=$!

# Ensure server is killed on script exit
trap "kill $SERVER_PID" EXIT

echo "Waiting for server to start (30s)..."
sleep 30

echo "Checking server status..."
SERVER_RESPONSE=$(curl -s -v http://localhost:3000 2>&1)
if echo "$SERVER_RESPONSE" | grep -q "Child compilation failed"; then
echo "Server started but has compilation errors. Exiting."
echo "$SERVER_RESPONSE"
exit 1
fi

if ! echo "$SERVER_RESPONSE" | grep -q "200 OK"; then
echo "Server did not return 200 OK. Exiting."
echo "$SERVER_RESPONSE"
exit 1
fi
echo "Server is healthy."

echo "Running Cypress tests..."
npm run cypress

90 changes: 46 additions & 44 deletions packages/react-router/src/ReactRouter/IonReactHashRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,55 @@
import type { Action as HistoryAction, History, Location as HistoryLocation } from 'history';
import { createHashHistory as createHistory } from 'history';
import React from 'react';
import type { BrowserRouterProps } from 'react-router-dom';
import { Router } from 'react-router-dom';
/**
* `IonReactHashRouter` provides a way to use hash-based routing in Ionic
* React applications.
*/

import type { Action as HistoryAction, Location as HistoryLocation } from 'history';
import type { PropsWithChildren } from 'react';
import React, { useEffect, useRef } from 'react';
import type { HashRouterProps } from 'react-router-dom';
import { HashRouter, useLocation, useNavigationType } from 'react-router-dom';

import { IonRouter } from './IonRouter';

interface IonReactHashRouterProps extends BrowserRouterProps {
history?: History;
}
const RouterContent = ({ children }: PropsWithChildren<{}>) => {
const location = useLocation();
const navigationType = useNavigationType();

export class IonReactHashRouter extends React.Component<IonReactHashRouterProps> {
history: History;
historyListenHandler?: (location: HistoryLocation, action: HistoryAction) => void;
const historyListenHandler = useRef<(location: HistoryLocation, action: HistoryAction) => void>();

constructor(props: IonReactHashRouterProps) {
super(props);
const { history, ...rest } = props;
this.history = history || createHistory(rest);
this.history.listen(this.handleHistoryChange.bind(this));
this.registerHistoryListener = this.registerHistoryListener.bind(this);
}
const registerHistoryListener = (cb: (location: HistoryLocation, action: HistoryAction) => void) => {
historyListenHandler.current = cb;
};

/**
* history@4.x passes separate location and action
* params. history@5.x passes location and action
* together as a single object.
* TODO: If support for React Router <=5 is dropped
* this logic is no longer needed. We can just assume
* a single object with both location and action.
* Processes navigation changes within the application.
*
* Its purpose is to relay the current `location` and the associated
* `action` ('PUSH', 'POP', or 'REPLACE') to any registered listeners,
* primarily for `IonRouter` to manage Ionic-specific UI updates and
* navigation stack behavior.
*
* @param location The current browser history location object.
* @param action The type of navigation action ('PUSH', 'POP', or
* 'REPLACE').
*/
handleHistoryChange(location: HistoryLocation, action: HistoryAction) {
const locationValue = (location as any).location || location;
const actionValue = (location as any).action || action;
if (this.historyListenHandler) {
this.historyListenHandler(locationValue, actionValue);
const handleHistoryChange = (location: HistoryLocation, action: HistoryAction) => {
if (historyListenHandler.current) {
historyListenHandler.current(location, action);
}
}

registerHistoryListener(cb: (location: HistoryLocation, action: HistoryAction) => void) {
this.historyListenHandler = cb;
}

render() {
const { children, ...props } = this.props;
return (
<Router history={this.history} {...props}>
<IonRouter registerHistoryListener={this.registerHistoryListener}>{children}</IonRouter>
</Router>
);
}
}
};

useEffect(() => {
handleHistoryChange(location, navigationType);
}, [location, navigationType]);

return <IonRouter registerHistoryListener={registerHistoryListener}>{children}</IonRouter>;
};

export const IonReactHashRouter = ({ children, ...routerProps }: PropsWithChildren<HashRouterProps>) => {
return (
<HashRouter {...routerProps}>
<RouterContent>{children}</RouterContent>
</HashRouter>
);
};
87 changes: 46 additions & 41 deletions packages/react-router/src/ReactRouter/IonReactMemoryRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,56 @@
import type { Action as HistoryAction, Location as HistoryLocation, MemoryHistory } from 'history';
import React from 'react';
/**
* `IonReactMemoryRouter` provides a way to use `react-router` in
* environments where a traditional browser history (like `BrowserRouter`)
* isn't available or desirable.
*/

import type { Action as HistoryAction, Location as HistoryLocation } from 'history';
import type { PropsWithChildren } from 'react';
import React, { useEffect, useRef } from 'react';
import type { MemoryRouterProps } from 'react-router';
import { Router } from 'react-router';
import { MemoryRouter, useLocation, useNavigationType } from 'react-router';

import { IonRouter } from './IonRouter';

interface IonReactMemoryRouterProps extends MemoryRouterProps {
history: MemoryHistory;
}
const RouterContent = ({ children }: PropsWithChildren<{}>) => {
const location = useLocation();
const navigationType = useNavigationType();

export class IonReactMemoryRouter extends React.Component<IonReactMemoryRouterProps> {
history: MemoryHistory;
historyListenHandler?: (location: HistoryLocation, action: HistoryAction) => void;
const historyListenHandler = useRef<(location: HistoryLocation, action: HistoryAction) => void>();

constructor(props: IonReactMemoryRouterProps) {
super(props);
this.history = props.history;
this.history.listen(this.handleHistoryChange.bind(this));
this.registerHistoryListener = this.registerHistoryListener.bind(this);
}
const registerHistoryListener = (cb: (location: HistoryLocation, action: HistoryAction) => void) => {
historyListenHandler.current = cb;
};

/**
* history@4.x passes separate location and action
* params. history@5.x passes location and action
* together as a single object.
* TODO: If support for React Router <=5 is dropped
* this logic is no longer needed. We can just assume
* a single object with both location and action.
* Processes navigation changes within the application.
*
* Its purpose is to relay the current `location` and the associated
* `action` ('PUSH', 'POP', or 'REPLACE') to any registered listeners,
* primarily for `IonRouter` to manage Ionic-specific UI updates and
* navigation stack behavior.
*
* @param location The current browser history location object.
* @param action The type of navigation action ('PUSH', 'POP', or
* 'REPLACE').
*/
handleHistoryChange(location: HistoryLocation, action: HistoryAction) {
const locationValue = (location as any).location || location;
const actionValue = (location as any).action || action;
if (this.historyListenHandler) {
this.historyListenHandler(locationValue, actionValue);
const handleHistoryChange = (location: HistoryLocation, action: HistoryAction) => {
if (historyListenHandler.current) {
historyListenHandler.current(location, action);
}
}

registerHistoryListener(cb: (location: HistoryLocation, action: HistoryAction) => void) {
this.historyListenHandler = cb;
}

render() {
const { children, ...props } = this.props;
return (
<Router {...props}>
<IonRouter registerHistoryListener={this.registerHistoryListener}>{children}</IonRouter>
</Router>
);
}
}
};

useEffect(() => {
handleHistoryChange(location, navigationType);
}, [location, navigationType]);

return <IonRouter registerHistoryListener={registerHistoryListener}>{children}</IonRouter>;
};

export const IonReactMemoryRouter = ({ children, ...routerProps }: PropsWithChildren<MemoryRouterProps>) => {
return (
<MemoryRouter {...routerProps}>
<RouterContent>{children}</RouterContent>
</MemoryRouter>
);
};
Loading
Loading