diff --git a/packages/react-router/src/ReactRouter/IonRouter.tsx b/packages/react-router/src/ReactRouter/IonRouter.tsx index 3d8ee90636..434b1b10a5 100644 --- a/packages/react-router/src/ReactRouter/IonRouter.tsx +++ b/packages/react-router/src/ReactRouter/IonRouter.tsx @@ -166,6 +166,13 @@ class IonRouterInner extends React.PureComponent { // 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); diff --git a/packages/react-router/test-app/cypress/integration/replace-actions.spec.js b/packages/react-router/test-app/cypress/integration/replace-actions.spec.js new file mode 100644 index 0000000000..93123ac3ce --- /dev/null +++ b/packages/react-router/test-app/cypress/integration/replace-actions.spec.js @@ -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') + }) + + + +}) diff --git a/packages/react-router/test-app/cypress/support/commands.js b/packages/react-router/test-app/cypress/support/commands.js index 714f11f614..6f08b7965a 100644 --- a/packages/react-router/test-app/cypress/support/commands.js +++ b/packages/react-router/test-app/cypress/support/commands.js @@ -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) }); diff --git a/packages/react-router/test-app/src/App.tsx b/packages/react-router/test-app/src/App.tsx index d888863a81..2a7113d640 100644 --- a/packages/react-router/test-app/src/App.tsx +++ b/packages/react-router/test-app/src/App.tsx @@ -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 = () => { + diff --git a/packages/react-router/test-app/src/pages/Main.tsx b/packages/react-router/test-app/src/pages/Main.tsx index 057b271ecd..1b2dccdf73 100644 --- a/packages/react-router/test-app/src/pages/Main.tsx +++ b/packages/react-router/test-app/src/pages/Main.tsx @@ -32,10 +32,13 @@ const Main: React.FC = () => { Nested Outlet 2 + + Replace Action + ); }; -export default Main; \ No newline at end of file +export default Main; diff --git a/packages/react-router/test-app/src/pages/replace-action/Replace.tsx b/packages/react-router/test-app/src/pages/replace-action/Replace.tsx new file mode 100644 index 0000000000..d02e024c04 --- /dev/null +++ b/packages/react-router/test-app/src/pages/replace-action/Replace.tsx @@ -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 = () => { + return ( + + + + + } /> + + ); +}; + +const Page1: React.FC = () => ( + + + + + + + Page one + + + + + Goto Page2 + + + +); + +const Page2: React.FC = () => { + + const history = useHistory(); + + const clickButton = () => { + history.replace('/replace-action/page3'); + }; + + return ( + + + + + + + Page two + + + + clickButton()}> + Goto Page3 + + + + ); +}; + +const Edit: React.FC = () => { + return ( + + + + + + + Page three + + + +

Page 3

+
+
+ ); +}; + +export default ReplaceAction; diff --git a/packages/react-router/test-app/src/pages/routing/Routing.tsx b/packages/react-router/test-app/src/pages/routing/Routing.tsx index 86a42a5b59..28ce52728c 100644 --- a/packages/react-router/test-app/src/pages/routing/Routing.tsx +++ b/packages/react-router/test-app/src/pages/routing/Routing.tsx @@ -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 = () => { }} /> */} -
Not found
} /> {/* } /> */} @@ -45,4 +43,4 @@ const Routing: React.FC = () => { ); }; -export default Routing; \ No newline at end of file +export default Routing; diff --git a/packages/react-router/test-app/src/pages/routing/TopPage.tsx b/packages/react-router/test-app/src/pages/routing/TopPage.tsx deleted file mode 100644 index ab124f916b..0000000000 --- a/packages/react-router/test-app/src/pages/routing/TopPage.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonButton } from '@ionic/react'; - -interface TopPageProps { -} - -const TopPage: React.FC = () => { - return ( - - - - TopPage - - - - - Go to Other Page - - - - ); -}; - -export default TopPage; \ No newline at end of file