fix(react): support routes without a path for notfound routes, fixes #20259 (#20261)

This commit is contained in:
Ely Lucas
2020-01-21 16:12:42 -07:00
parent f971f76b4b
commit 85be000a4c
4 changed files with 41 additions and 17 deletions

View File

@ -1,6 +1,6 @@
import { RouteProps, match } from 'react-router-dom';
export interface IonRouteData {
match: match<{ tab: string }> | null;
match: match | null;
childProps: RouteProps;
}

View File

@ -255,12 +255,23 @@ export class RouteManager extends React.Component<RouteManagerProps, RouteManage
const views: ViewItem[] = [];
let activeId: string | undefined;
const ionRouterOutlet = React.Children.only(children) as React.ReactElement;
let foundMatch = false;
React.Children.forEach(ionRouterOutlet.props.children, (child: React.ReactElement) => {
const routeId = generateId();
this.routes[routeId] = child;
views.push(createViewItem(child, routeId, this.props.history.location));
});
if (!foundMatch) {
const notFoundRoute = views.find(r => {
// try to find a route that doesn't have a path or from prop, that will be our not found route
return !r.routeData.childProps.path && !r.routeData.childProps.from;
});
if (notFoundRoute) {
notFoundRoute.show = true;
}
}
this.registerViewStack(id, activeId, views, routerOutlet, this.props.location);
function createViewItem(child: React.ReactElement<any>, routeId: string, location: HistoryLocation) {
@ -289,6 +300,9 @@ export class RouteManager extends React.Component<RouteManagerProps, RouteManage
if (match && view.isIonRoute) {
activeId = viewId;
}
if (!foundMatch && match) {
foundMatch = true;
}
return view;
}
}
@ -360,7 +374,7 @@ export class RouteManager extends React.Component<RouteManagerProps, RouteManage
React.Children.forEach(ionRouterOutlet.props.children, (child: React.ReactElement) => {
for (const routeKey in this.routes) {
const route = this.routes[routeKey];
if (route.props.path === child.props.path) {
if (typeof route.props.path !== 'undefined' && route.props.path === (child.props.path || child.props.from)) {
this.routes[routeKey] = child;
}
}

View File

@ -65,6 +65,7 @@ export class View extends React.Component<ViewProps, {}> {
...value,
registerIonPage: this.registerIonPage.bind(this)
};
return (
<NavContext.Provider value={newProvider}>
{this.props.children}

View File

@ -13,7 +13,7 @@ export interface ViewStack {
* The holistic view of all the Routes configured for an application inside of an IonRouterOutlet.
*/
export class ViewStacks {
private viewStacks: { [key: string]: ViewStack | undefined } = {};
private viewStacks: { [key: string]: ViewStack | undefined; } = {};
get(key: string) {
return this.viewStacks[key];
@ -31,25 +31,34 @@ export class ViewStacks {
delete this.viewStacks[key];
}
findViewInfoByLocation(location: HistoryLocation, viewKey?: string) {
findViewInfoByLocation(location: HistoryLocation, viewKey: string) {
let view: ViewItem<IonRouteData> | undefined;
let match: IonRouteData['match'] | null | undefined;
let viewStack: ViewStack | undefined;
if (viewKey) {
viewStack = this.viewStacks[viewKey];
if (viewStack) {
viewStack.views.some(matchView);
viewStack = this.viewStacks[viewKey];
if (viewStack) {
viewStack.views.some(matchView);
if (!view) {
viewStack.views.some(r => {
// try to find a route that doesn't have a path or from prop, that will be our not found route
if (!r.routeData.childProps.path && !r.routeData.childProps.from) {
match = {
path: location.pathname,
url: location.pathname,
isExact: true,
params: {}
};
view = r;
return true;
}
return false;
});
}
} else {
const keys = this.getKeys();
keys.some(key => {
viewStack = this.viewStacks[key];
return viewStack!.views.some(matchView);
});
}
const result = { view, viewStack, match };
return result;
return { view, viewStack, match };
function matchView(v: ViewItem) {
const matchProps = {
@ -61,7 +70,7 @@ export class ViewStacks {
if (myMatch) {
view = v;
match = myMatch;
return view.location === location.pathname;
return true;
}
return false;
}