fix(react-router): addressing some migration issues with memory and hash router

This commit is contained in:
ShaneK
2025-10-08 09:42:54 -07:00
parent 0949a878b4
commit 8fd53b2cb8
5 changed files with 48 additions and 19 deletions

View File

@@ -11,7 +11,7 @@ import { HashRouter, useLocation, useNavigationType } from 'react-router-dom';
import { IonRouter } from './IonRouter';
export const IonReactHashRouter = ({ children }: PropsWithChildren<HashRouterProps>) => {
const RouterContent = ({ children }: PropsWithChildren<{}>) => {
const location = useLocation();
const navigationType = useNavigationType();
@@ -43,9 +43,13 @@ export const IonReactHashRouter = ({ children }: PropsWithChildren<HashRouterPro
handleHistoryChange(location, navigationType);
}, [location, navigationType]);
return <IonRouter registerHistoryListener={registerHistoryListener}>{children}</IonRouter>;
};
export const IonReactHashRouter = ({ children, ...routerProps }: PropsWithChildren<HashRouterProps>) => {
return (
<HashRouter>
<IonRouter registerHistoryListener={registerHistoryListener}>{children}</IonRouter>
<HashRouter {...routerProps}>
<RouterContent>{children}</RouterContent>
</HashRouter>
);
};

View File

@@ -8,12 +8,11 @@ import type { Action as HistoryAction, Location as HistoryLocation } from 'histo
import type { PropsWithChildren } from 'react';
import React, { useEffect, useRef } from 'react';
import type { MemoryRouterProps } from 'react-router';
import { MemoryRouter } from 'react-router';
import { useLocation, useNavigationType } from 'react-router-dom';
import { MemoryRouter, useLocation, useNavigationType } from 'react-router';
import { IonRouter } from './IonRouter';
export const IonReactMemoryRouter = ({ children }: PropsWithChildren<MemoryRouterProps>) => {
const RouterContent = ({ children }: PropsWithChildren<{}>) => {
const location = useLocation();
const navigationType = useNavigationType();
@@ -45,9 +44,13 @@ export const IonReactMemoryRouter = ({ children }: PropsWithChildren<MemoryRoute
handleHistoryChange(location, navigationType);
}, [location, navigationType]);
return <IonRouter registerHistoryListener={registerHistoryListener}>{children}</IonRouter>;
};
export const IonReactMemoryRouter = ({ children, ...routerProps }: PropsWithChildren<MemoryRouterProps>) => {
return (
<MemoryRouter>
<IonRouter registerHistoryListener={registerHistoryListener}>{children}</IonRouter>
<MemoryRouter {...routerProps}>
<RouterContent>{children}</RouterContent>
</MemoryRouter>
);
};

View File

@@ -535,9 +535,27 @@ export class ReactRouterViewStack extends ViewStacks {
/**
* Matches a view with no path prop (default fallback route) or index route.
*/
function matchDefaultRoute(): boolean {
// Don't use view items with no path as default matches for different pathnames
// This prevents index routes from incorrectly matching other routes
function matchDefaultRoute(v: ViewItem): boolean {
const childProps = v.routeData.childProps;
const isDefaultRoute = childProps.path === undefined || childProps.path === '';
const isIndexRoute = !!childProps.index;
if (isDefaultRoute || isIndexRoute) {
match = {
params: {},
pathname,
pathnameBase: pathname === '' ? '/' : pathname,
pattern: {
path: '',
caseSensitive: childProps.caseSensitive ?? false,
end: true,
},
};
viewItem = v;
return true;
}
return false;
}
}

View File

@@ -5,7 +5,7 @@
*/
import type { RouteInfo, StackContextState, ViewItem } from '@ionic/react';
import { RouteManagerContext, StackContext, getConfig } from '@ionic/react';
import { RouteManagerContext, StackContext, generateId, getConfig } from '@ionic/react';
import React from 'react';
import { Route } from 'react-router-dom';
@@ -47,9 +47,8 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
this.registerIonPage = this.registerIonPage.bind(this);
this.transitionPage = this.transitionPage.bind(this);
this.handlePageTransition = this.handlePageTransition.bind(this);
// Use provided id prop if available; otherwise use a stable default id so
// view items are associated to the same outlet across re-renders.
this.id = props.id || 'routerOutlet';
// Use provided id prop if available; otherwise generate a unique id.
this.id = props.id || `routerOutlet-${generateId('routerOutlet')}`;
this.prevProps = undefined;
this.skipTransition = false;
}

View File

@@ -7,11 +7,13 @@ import OutletPageManager from '../routing/OutletPageManager';
import type { IonicReactProps } from './IonicReactProps';
import { IonRouterOutletInner } from './inner-proxies';
import { createForwardRef } from './utils';
import { generateId } from '../utils/generateId';
type Props = LocalJSX.IonRouterOutlet & {
basePath?: string;
ref?: React.Ref<any>;
ionPage?: boolean;
id?: string;
};
interface InternalProps extends Props {
@@ -23,16 +25,19 @@ interface InternalState {}
class IonRouterOutletContainer extends React.Component<InternalProps, InternalState> {
context!: React.ContextType<typeof NavContext>;
private readonly outletId: string;
constructor(props: InternalProps) {
super(props);
this.outletId = props.id ?? `routerOutlet-${generateId('routerOutlet')}`;
}
render() {
const StackManager = this.context.getStackManager();
const { children, forwardedRef, ...props } = this.props;
console.log(`[IonRouterOutlet] Rendering with id: "${props.id}", all props:`, Object.keys(props));
const outletId = props.id ?? this.outletId;
console.log(`[IonRouterOutlet] Rendering with id: "${outletId}", all props:`, Object.keys(props));
return this.context.hasIonicRouter() ? (
props.ionPage ? (
@@ -40,8 +45,8 @@ class IonRouterOutletContainer extends React.Component<InternalProps, InternalSt
{children}
</OutletPageManager>
) : (
<StackManager routeInfo={this.context.routeInfo} id={props.id}>
<IonRouterOutletInner {...props} forwardedRef={forwardedRef}>
<StackManager routeInfo={this.context.routeInfo} id={outletId}>
<IonRouterOutletInner {...props} id={outletId} forwardedRef={forwardedRef}>
{children}
</IonRouterOutletInner>
</StackManager>