mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix(react, vue): correct view now chosen when going back inside tabs (#23154)
resolves #23087 resolves #23101
This commit is contained in:
@@ -243,7 +243,19 @@ class IonRouterInner extends React.PureComponent<IonRouteProps, IonRouteState> {
|
||||
routeDirection: 'back',
|
||||
routeAnimation: routeAnimation || routeInfo.routeAnimation,
|
||||
};
|
||||
if (routeInfo.lastPathname === routeInfo.pushedByRoute || prevInfo.pathname === routeInfo.pushedByRoute) {
|
||||
if (
|
||||
routeInfo.lastPathname === routeInfo.pushedByRoute ||
|
||||
(
|
||||
/**
|
||||
* We need to exclude tab switches/tab
|
||||
* context changes here because tabbed
|
||||
* navigation is not linear, but router.back()
|
||||
* will go back in a linear fashion.
|
||||
*/
|
||||
prevInfo.pathname === routeInfo.pushedByRoute &&
|
||||
routeInfo.tab === '' && prevInfo.tab === ''
|
||||
)
|
||||
) {
|
||||
this.props.history.goBack();
|
||||
} else {
|
||||
this.handleNavigate(prevInfo.pathname + (prevInfo.search || ''), 'pop', 'back');
|
||||
|
||||
46
packages/react-router/test-app/cypress/integration/tabs.js
vendored
Normal file
46
packages/react-router/test-app/cypress/integration/tabs.js
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
const port = 3000;
|
||||
|
||||
describe('Tabs', () => {
|
||||
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/23101
|
||||
it('should return to previous tab instance when using the ion-back-button', () => {
|
||||
cy.visit(`http://localhost:${port}/tabs/tab1`);
|
||||
|
||||
cy.get('#tabs-secondary').click();
|
||||
cy.ionPageVisible('tab1-secondary');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab2-secondary').click();
|
||||
cy.ionPageHidden('tab1-secondary');
|
||||
cy.ionPageVisible('tab2-secondary');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab1-secondary').click();
|
||||
cy.ionPageHidden('tab2-secondary');
|
||||
cy.ionPageVisible('tab1-secondary');
|
||||
|
||||
cy.ionBackClick('tab1-secondary');
|
||||
cy.ionPageDoesNotExist('tabs-secondary');
|
||||
cy.ionPageVisible('tab1');
|
||||
});
|
||||
|
||||
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/23087
|
||||
it('should return to correct view and url when going back from child page after switching tabs', () => {
|
||||
cy.visit(`http://localhost:${port}/tabs/tab1`);
|
||||
|
||||
cy.get('#child-one').click();
|
||||
cy.ionPageHidden('tab1');
|
||||
cy.ionPageVisible('tab1child1');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab2').click();
|
||||
cy.ionPageHidden('tab1child1');
|
||||
cy.ionPageVisible('tab2');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab1').click();
|
||||
cy.ionPageHidden('tab2');
|
||||
cy.ionPageVisible('tab1child1');
|
||||
|
||||
cy.ionBackClick('tab1child1');
|
||||
cy.ionPageDoesNotExist('tab1child1');
|
||||
cy.ionPageVisible('tab1');
|
||||
|
||||
cy.url().should('include', '/tabs/tab1');
|
||||
});
|
||||
});
|
||||
@@ -34,6 +34,8 @@ import { OutletRef } from './pages/outlet-ref/OutletRef';
|
||||
import { SwipeToGoBack } from './pages/swipe-to-go-back/SwipToGoBack';
|
||||
import Refs from './pages/refs/Refs';
|
||||
import DynamicIonpageClassnames from './pages/dynamic-ionpage-classnames/DynamicIonpageClassnames';
|
||||
import Tabs from './pages/tabs/Tabs';
|
||||
import TabsSecondary from './pages/tabs/TabsSecondary';
|
||||
debugger;
|
||||
const App: React.FC = () => {
|
||||
return (
|
||||
@@ -51,6 +53,8 @@ const App: React.FC = () => {
|
||||
<Route path="/outlet-ref" component={OutletRef} />
|
||||
<Route path="/swipe-to-go-back" component={SwipeToGoBack} />
|
||||
<Route path="/dynamic-ionpage-classnames" component={DynamicIonpageClassnames} />
|
||||
<Route path="/tabs" component={Tabs} />
|
||||
<Route path="/tabs-secondary" component={TabsSecondary} />
|
||||
<Route path="/refs" component={Refs} />
|
||||
</IonReactRouter>
|
||||
</IonApp>
|
||||
|
||||
95
packages/react-router/test-app/src/pages/tabs/Tabs.tsx
Normal file
95
packages/react-router/test-app/src/pages/tabs/Tabs.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
IonTabs,
|
||||
IonRouterOutlet,
|
||||
IonTabBar,
|
||||
IonTabButton,
|
||||
IonIcon,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonHeader,
|
||||
IonToolbar,
|
||||
IonButtons,
|
||||
IonBackButton,
|
||||
IonTitle,
|
||||
IonContent,
|
||||
IonButton,
|
||||
} from '@ionic/react';
|
||||
import { Route, Redirect } from 'react-router';
|
||||
import { triangle, square } from 'ionicons/icons';
|
||||
|
||||
interface Tabs {}
|
||||
|
||||
const Tabs: React.FC<Tabs> = () => {
|
||||
return (
|
||||
<IonTabs>
|
||||
<IonRouterOutlet id="tabs">
|
||||
<Route path="/tabs/tab1" component={Tab1} exact />
|
||||
<Route path="/tabs/tab2" component={Tab2} exact />
|
||||
<Route path="/tabs/tab1/child" component={Tab1Child1} exact />
|
||||
<Redirect from="/tabs" to="/tabs/tab1" exact />
|
||||
</IonRouterOutlet>
|
||||
<IonTabBar slot="bottom">
|
||||
<IonTabButton tab="tab1" href="/tabs/tab1">
|
||||
<IonIcon icon={triangle} />
|
||||
<IonLabel>Tab1</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="tab2" href="/tabs/tab2">
|
||||
<IonIcon icon={square} />
|
||||
<IonLabel>Tab2</IonLabel>
|
||||
</IonTabButton>
|
||||
</IonTabBar>
|
||||
</IonTabs>
|
||||
);
|
||||
};
|
||||
|
||||
const Tab1 = () => {
|
||||
return (
|
||||
<IonPage data-pageid="tab1">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Tab1</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonButton routerLink="/tabs/tab1/child" id="child-one">Go to Tab1Child1</IonButton>
|
||||
<IonButton routerLink="/tabs-secondary/tab1" id="tabs-secondary">Go to Secondary Tabs</IonButton>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
const Tab1Child1 = () => {
|
||||
return (
|
||||
<IonPage data-pageid="tab1child1">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton />
|
||||
</IonButtons>
|
||||
<IonTitle>Tab1</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
const Tab2 = () => {
|
||||
return (
|
||||
<IonPage data-pageid="tab2">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Tab2</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
Tab 2
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tabs;
|
||||
@@ -0,0 +1,78 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
IonTabs,
|
||||
IonRouterOutlet,
|
||||
IonTabBar,
|
||||
IonTabButton,
|
||||
IonIcon,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonHeader,
|
||||
IonToolbar,
|
||||
IonButtons,
|
||||
IonBackButton,
|
||||
IonTitle,
|
||||
IonContent,
|
||||
IonButton,
|
||||
} from '@ionic/react';
|
||||
import { Route, Redirect } from 'react-router';
|
||||
import { triangle, square } from 'ionicons/icons';
|
||||
|
||||
interface TabsSecondary {}
|
||||
|
||||
const TabsSecondary: React.FC<TabsSecondary> = () => {
|
||||
return (
|
||||
<IonTabs>
|
||||
<IonRouterOutlet id="tabs-secondary">
|
||||
<Route path="/tabs-secondary/tab1" component={Tab1} exact />
|
||||
<Route path="/tabs-secondary/tab2" component={Tab2} exact />
|
||||
<Redirect from="/tabs-secondary" to="/tabs-secondary/tab1" exact />
|
||||
</IonRouterOutlet>
|
||||
<IonTabBar slot="bottom">
|
||||
<IonTabButton tab="tab1-secondary" href="/tabs-secondary/tab1">
|
||||
<IonIcon icon={triangle} />
|
||||
<IonLabel>Tab1</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="tab2-secondary" href="/tabs-secondary/tab2">
|
||||
<IonIcon icon={square} />
|
||||
<IonLabel>Tab2</IonLabel>
|
||||
</IonTabButton>
|
||||
</IonTabBar>
|
||||
</IonTabs>
|
||||
);
|
||||
};
|
||||
|
||||
const Tab1 = () => {
|
||||
return (
|
||||
<IonPage data-pageid="tab1-secondary">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Tab1</IonTitle>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
Tab 1
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
const Tab2 = () => {
|
||||
return (
|
||||
<IonPage data-pageid="tab2-secondary">
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Tab2</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
Tab 2
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default TabsSecondary;
|
||||
@@ -88,7 +88,19 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
||||
const prevInfo = locationHistory.findLastLocation(routeInfo);
|
||||
if (prevInfo) {
|
||||
incomingRouteParams = { ...prevInfo, routerAction: 'pop', routerDirection: 'back', routerAnimation: routerAnimation || routeInfo.routerAnimation };
|
||||
if (routeInfo.lastPathname === routeInfo.pushedByRoute || prevInfo.pathname === routeInfo.pushedByRoute) {
|
||||
if (
|
||||
routeInfo.lastPathname === routeInfo.pushedByRoute ||
|
||||
(
|
||||
/**
|
||||
* We need to exclude tab switches/tab
|
||||
* context changes here because tabbed
|
||||
* navigation is not linear, but router.back()
|
||||
* will go back in a linear fashion.
|
||||
*/
|
||||
prevInfo.pathname === routeInfo.pushedByRoute &&
|
||||
routeInfo.tab === '' && prevInfo.tab === ''
|
||||
)
|
||||
) {
|
||||
router.back();
|
||||
} else {
|
||||
router.replace({ path: prevInfo.pathname, query: parseQuery(prevInfo.search) });
|
||||
|
||||
@@ -220,6 +220,50 @@ describe('Tabs', () => {
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab1').should('not.have.class', 'tab-selected');
|
||||
});
|
||||
|
||||
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/23101
|
||||
it('should return to previous tab instance when using the ion-back-button', () => {
|
||||
cy.visit('http://localhost:8080/tabs/tab1');
|
||||
|
||||
cy.get('#tabs-secondary').click();
|
||||
cy.ionPageHidden('tabs');
|
||||
cy.ionPageVisible('tab1-secondary');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab2-secondary').click();
|
||||
cy.ionPageHidden('tab1-secondary');
|
||||
cy.ionPageVisible('tab2-secondary');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab1-secondary').click();
|
||||
cy.ionPageHidden('tab2-secondary');
|
||||
cy.ionPageVisible('tab1-secondary');
|
||||
|
||||
cy.ionBackClick('tab1-secondary');
|
||||
cy.ionPageDoesNotExist('tabs-secondary');
|
||||
cy.ionPageVisible('tab1');
|
||||
});
|
||||
|
||||
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/23087
|
||||
it('should return to correct view and url when going back from child page after switching tabs', () => {
|
||||
cy.visit('http://localhost:8080/tabs/tab1');
|
||||
|
||||
cy.get('#child-one').click();
|
||||
cy.ionPageHidden('tab1');
|
||||
cy.ionPageVisible('tab1childone');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab2').click();
|
||||
cy.ionPageHidden('tab1childone');
|
||||
cy.ionPageVisible('tab2');
|
||||
|
||||
cy.get('ion-tab-button#tab-button-tab1').click();
|
||||
cy.ionPageHidden('tab2');
|
||||
cy.ionPageVisible('tab1childone');
|
||||
|
||||
cy.ionBackClick('tab1childone');
|
||||
cy.ionPageDoesNotExist('tab1childone');
|
||||
cy.ionPageVisible('tab1');
|
||||
|
||||
cy.url().should('include', '/tabs/tab1');
|
||||
});
|
||||
})
|
||||
|
||||
describe('Tabs - Swipe to Go Back', () => {
|
||||
|
||||
Reference in New Issue
Block a user