mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-12-19 05:19:42 +08:00
fix(react-router): addressing some migration issues with memory and hash router
This commit is contained in:
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user