fix(react): Do a better job matching up route to sync, fixes #20363 (#20446)

This commit is contained in:
Ely Lucas
2020-02-11 16:40:38 -07:00
parent b6fbe98812
commit c0aadd6007
4 changed files with 24 additions and 4 deletions

View File

@ -4,7 +4,7 @@ import { ViewStacks } from './ViewStacks';
export interface RouteManagerContextState { export interface RouteManagerContextState {
syncView: (page: HTMLElement, viewId: string) => void; syncView: (page: HTMLElement, viewId: string) => void;
syncRoute: (id: string, route: any) => void; syncRoute: (route: any) => void;
hideView: (viewId: string) => void; hideView: (viewId: string) => void;
viewStacks: ViewStacks; viewStacks: ViewStacks;
setupIonRouter: (id: string, children: ReactNode, routerOutlet: HTMLIonRouterOutletElement) => void; setupIonRouter: (id: string, children: ReactNode, routerOutlet: HTMLIonRouterOutletElement) => void;

View File

@ -368,13 +368,17 @@ export class RouteManager extends React.Component<RouteManagerProps, RouteManage
} }
} }
syncRoute(_id: string, routerOutlet: any) { syncRoute(routerOutlet: any) {
const ionRouterOutlet = React.Children.only(routerOutlet) as React.ReactElement; const ionRouterOutlet = React.Children.only(routerOutlet) as React.ReactElement;
React.Children.forEach(ionRouterOutlet.props.children, (child: React.ReactElement) => { React.Children.forEach(ionRouterOutlet.props.children, (child: React.ReactElement) => {
for (const routeKey in this.routes) { for (const routeKey in this.routes) {
const route = this.routes[routeKey]; const route = this.routes[routeKey];
if (typeof route.props.path !== 'undefined' && route.props.path === (child.props.path || child.props.from)) { if (
((route.props.path || route.props.from) === (child.props.path || child.props.from)) &&
(route.props.exact === child.props.exact) &&
(route.props.to === child.props.to)
) {
this.routes[routeKey] = child; this.routes[routeKey] = child;
} }
} }

View File

@ -32,7 +32,7 @@ class StackManagerInner extends React.Component<StackManagerProps, StackManagerS
} }
static getDerivedStateFromProps(props: StackManagerProps, state: StackManagerState) { static getDerivedStateFromProps(props: StackManagerProps, state: StackManagerState) {
props.routeManager.syncRoute('', props.children); props.routeManager.syncRoute(props.children);
return state; return state;
} }

View File

@ -1,5 +1,6 @@
import { IonLifeCycleContext, NavContext } from '@ionic/react'; import { IonLifeCycleContext, NavContext } from '@ionic/react';
import React from 'react'; import React from 'react';
import { Redirect } from 'react-router';
import { isDevMode } from '../utils'; import { isDevMode } from '../utils';
@ -19,6 +20,21 @@ export class View extends React.Component<ViewProps, {}> {
context!: React.ContextType<typeof IonLifeCycleContext>; context!: React.ContextType<typeof IonLifeCycleContext>;
ionPage?: HTMLElement; ionPage?: HTMLElement;
componentDidMount() {
/**
* If we can tell if view is a redirect, hide it so it will work again in future
*/
const { view, route } = this.props;
if (route.type === Redirect) {
this.props.onHideView(view.id);
} else if (route.props.render && !view.isIonRoute) {
// Test the render to see if it returns a redirect
if (route.props.render().type === Redirect) {
this.props.onHideView(view.id);
}
}
}
componentWillUnmount() { componentWillUnmount() {
if (this.ionPage) { if (this.ionPage) {
this.ionPage.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this)); this.ionPage.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this));