fix(react): fix regression with history.replace in new react router (#21698)
This commit is contained in:
parent
c171ccbd37
commit
81ef3f1ecd
|
@ -166,6 +166,13 @@ class IonRouterInner extends React.PureComponent<IonRouteProps, IonRouteState> {
|
|||
// If we are switching tabs grab the last route info for the tab and use its pushedByRoute
|
||||
const lastRoute = this.locationHistory.getCurrentRouteInfoForTab(routeInfo.tab);
|
||||
routeInfo.pushedByRoute = lastRoute?.pushedByRoute;
|
||||
} else if (routeInfo.routeAction === 'replace') {
|
||||
// Make sure to set the lastPathname, etc.. to the current route so the page transitions out
|
||||
const currentRouteInfo = this.locationHistory.current();
|
||||
routeInfo.lastPathname = currentRouteInfo?.pathname || routeInfo.lastPathname;
|
||||
routeInfo.pushedByRoute = currentRouteInfo?.pushedByRoute || routeInfo.pushedByRoute;
|
||||
routeInfo.routeDirection = currentRouteInfo?.routeDirection || routeInfo.routeDirection;
|
||||
routeInfo.routeAnimation = currentRouteInfo?.routeAnimation || routeInfo.routeAnimation;
|
||||
}
|
||||
|
||||
this.locationHistory.add(routeInfo);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
const port = 3000;
|
||||
|
||||
describe('Replace Action', () => {
|
||||
|
||||
/*
|
||||
This spec tests that when a 'replace' action is used, that it does replace the current
|
||||
history item in location history.
|
||||
*/
|
||||
|
||||
it('/replace-action > Goto Page2 > Goto Page3 > Browser Back > Page1 should be visible and Page2 should be gone', () => {
|
||||
cy.visit(`http://localhost:${port}/replace-action`)
|
||||
cy.ionPageVisible('page1')
|
||||
cy.ionNav('ion-button', 'Goto Page2')
|
||||
cy.ionPageVisible('page2')
|
||||
cy.ionNav('ion-button', 'Goto Page3')
|
||||
cy.ionPageVisible('page3')
|
||||
cy.go('back')
|
||||
cy.ionPageVisible('page1')
|
||||
cy.ionPageDoesNotExist('page2')
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
|
@ -47,6 +47,20 @@ Cypress.Commands.add('ionPageVisible', (pageId) => {
|
|||
// cy.get(`div.ion-page[data-pageid=${pageId}]`).should('have.attr', 'style', 'z-index: 101;')
|
||||
})
|
||||
|
||||
|
||||
Cypress.Commands.add('ionPageHidden', (pageId) => {
|
||||
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
||||
.should('have.class', 'ion-page-hidden')
|
||||
.should('have.class', 'ion-page-invisible')
|
||||
.should('have.length', 1)
|
||||
})
|
||||
|
||||
Cypress.Commands.add('ionPageDoesNotExist', (pageId) => {
|
||||
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
|
||||
Cypress.Commands.add('ionNav', (element, contains) => {
|
||||
cy.contains(element, contains).click();
|
||||
cy.wait(250);
|
||||
|
@ -77,7 +91,7 @@ Cypress.Commands.add('ionMenuNav', (contains) => {
|
|||
Cypress.Commands.add('ionTabClick', (tabText) => {
|
||||
// TODO: figure out how to get rid of this wait. Switching tabs after a forward nav to a details page needs it
|
||||
cy.wait(250)
|
||||
cy.contains('ion-tab-button', tabText).click({ force: true})
|
||||
cy.contains('ion-tab-button', tabText).click({ force: true })
|
||||
// cy.get('ion-tab-button.tab-selected').contains(tabText)
|
||||
});
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import MultipleTabs from './pages/muiltiple-tabs/MultipleTabs';
|
|||
import DynamicTabs from './pages/dynamic-tabs/DynamicTabs';
|
||||
import NestedOutlet from './pages/nested-outlet/NestedOutlet';
|
||||
import NestedOutlet2 from './pages/nested-outlet/NestedOutlet2';
|
||||
import ReplaceAction from './pages/replace-action/Replace';
|
||||
debugger;
|
||||
const App: React.FC = () => {
|
||||
return (
|
||||
|
@ -44,6 +45,7 @@ const App: React.FC = () => {
|
|||
<Route path="/dynamic-tabs" component={DynamicTabs} />
|
||||
<Route path="/nested-outlet" component={NestedOutlet} />
|
||||
<Route path="/nested-outlet2" component={NestedOutlet2} />
|
||||
<Route path="/replace-action" component={ReplaceAction} />
|
||||
|
||||
</IonReactRouter>
|
||||
</IonApp>
|
||||
|
|
|
@ -32,10 +32,13 @@ const Main: React.FC<MainProps> = () => {
|
|||
<IonItem routerLink="/nested-outlet2">
|
||||
<IonLabel>Nested Outlet 2</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem routerLink="/replace-action">
|
||||
<IonLabel>Replace Action</IonLabel>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Main;
|
||||
export default Main;
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
import React from 'react';
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonButton, IonRouterOutlet, IonButtons, IonBackButton } from '@ionic/react';
|
||||
import { Route, Redirect, useHistory } from 'react-router';
|
||||
|
||||
interface TopPageProps {
|
||||
}
|
||||
|
||||
const ReplaceAction: React.FC<TopPageProps> = () => {
|
||||
return (
|
||||
<IonRouterOutlet>
|
||||
<Route path="/replace-action/page1" component={Page1} exact />
|
||||
<Route path="/replace-action/page2" component={Page2} exact />
|
||||
<Route path="/replace-action/page3" component={Edit} exact />
|
||||
<Route exact path="/replace-action" render={() => <Redirect to="/replace-action/page1" />} />
|
||||
</IonRouterOutlet>
|
||||
);
|
||||
};
|
||||
|
||||
const Page1: React.FC = () => (
|
||||
<IonPage data-pageid="page1">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton />
|
||||
</IonButtons>
|
||||
<IonTitle>Page one</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonButton routerLink={'/replace-action/page2'}>
|
||||
Goto Page2
|
||||
</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
|
||||
const Page2: React.FC = () => {
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
const clickButton = () => {
|
||||
history.replace('/replace-action/page3');
|
||||
};
|
||||
|
||||
return (
|
||||
<IonPage data-pageid="page2">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton/>
|
||||
</IonButtons>
|
||||
<IonTitle>Page two</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonButton onClick={() => clickButton()}>
|
||||
Goto Page3
|
||||
</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
const Edit: React.FC = () => {
|
||||
return (
|
||||
<IonPage data-pageid="page3">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton defaultHref="/replace-action/page1"/>
|
||||
</IonButtons>
|
||||
<IonTitle>Page three</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<p>Page 3</p>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReplaceAction;
|
|
@ -6,7 +6,6 @@ import Tabs from './Tabs';
|
|||
import Favorites from './Favorites';
|
||||
import OtherPage from './OtherPage';
|
||||
import PropsTest from './PropsTest';
|
||||
import TopPage from './TopPage';
|
||||
|
||||
interface RoutingProps {
|
||||
}
|
||||
|
@ -36,7 +35,6 @@ const Routing: React.FC<RoutingProps> = () => {
|
|||
}} /> */}
|
||||
<Route path="/routing/otherpage" component={OtherPage} />
|
||||
<Route path="/routing/propstest" component={PropsTest} />
|
||||
<Route path="/routing/toppage" component={TopPage} />
|
||||
<Route render={() => <IonPage data-pageid="not-found"><IonContent><div>Not found</div></IonContent></IonPage>} />
|
||||
{/* <Route render={() => <Redirect to="/tabs" />} /> */}
|
||||
|
||||
|
@ -45,4 +43,4 @@ const Routing: React.FC<RoutingProps> = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default Routing;
|
||||
export default Routing;
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import React from 'react';
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonButton } from '@ionic/react';
|
||||
|
||||
interface TopPageProps {
|
||||
}
|
||||
|
||||
const TopPage: React.FC<TopPageProps> = () => {
|
||||
return (
|
||||
<IonPage data-pageid="toppage">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>TopPage</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonButton routerLink="/otherpage">
|
||||
Go to Other Page
|
||||
</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopPage;
|
Loading…
Reference in New Issue