diff --git a/packages/react-router/src/ReactRouter/IonRouter.tsx b/packages/react-router/src/ReactRouter/IonRouter.tsx index 94805b1153..2ac9b942e5 100644 --- a/packages/react-router/src/ReactRouter/IonRouter.tsx +++ b/packages/react-router/src/ReactRouter/IonRouter.tsx @@ -177,7 +177,7 @@ export const IonRouter = ({ children, registerHistoryListener }: PropsWithChildr } const leavingUrl = leavingLocationInfo.pathname + leavingLocationInfo.search; - if (leavingUrl !== location.pathname) { + if (leavingUrl !== location.pathname + location.search) { if (!incomingRouteParams.current) { // Determine if the destination is a tab route by checking if it matches // the pattern of tab routes (containing /tabs/ in the path) diff --git a/packages/react-router/test/base/src/App.tsx b/packages/react-router/test/base/src/App.tsx index 373de8adbb..9ebd4c2e78 100644 --- a/packages/react-router/test/base/src/App.tsx +++ b/packages/react-router/test/base/src/App.tsx @@ -46,6 +46,7 @@ import Overlays from './pages/overlays/Overlays'; import NestedTabsRelativeLinks from './pages/nested-tabs-relative-links/NestedTabsRelativeLinks'; import RootSplatTabs from './pages/root-splat-tabs/RootSplatTabs'; import ContentChangeNavigation from './pages/content-change-navigation/ContentChangeNavigation'; +import SearchParams from './pages/search-params/SearchParams'; setupIonicReact(); @@ -81,6 +82,7 @@ const App: React.FC = () => { } /> } /> } /> + } /> diff --git a/packages/react-router/test/base/src/pages/Main.tsx b/packages/react-router/test/base/src/pages/Main.tsx index c4032b4606..e901613b27 100644 --- a/packages/react-router/test/base/src/pages/Main.tsx +++ b/packages/react-router/test/base/src/pages/Main.tsx @@ -83,6 +83,9 @@ const Main: React.FC = () => { Content Change Navigation + + Search Params + diff --git a/packages/react-router/test/base/src/pages/search-params/SearchParams.tsx b/packages/react-router/test/base/src/pages/search-params/SearchParams.tsx new file mode 100644 index 0000000000..f69a1ca7e7 --- /dev/null +++ b/packages/react-router/test/base/src/pages/search-params/SearchParams.tsx @@ -0,0 +1,50 @@ +import { + IonBackButton, + IonButton, + IonButtons, + IonContent, + IonHeader, + IonPage, + IonTitle, + IonToolbar, +} from '@ionic/react'; +import React from 'react'; +import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; + +const SearchParams: React.FC = () => { + const navigate = useNavigate(); + const location = useLocation(); + const [searchParams] = useSearchParams(); + const query = searchParams.get('q') || ''; + + return ( + + + + + + + Search Params + + + +
{location.pathname + location.search}
+
{query}
+ navigate('/search-params?q=test')}> + Add Search Param + + navigate('/search-params?q=changed')}> + Change Search Param + + navigate('/search-params')}> + Remove Search Param + + + Go Home + +
+
+ ); +}; + +export default SearchParams; diff --git a/packages/react-router/test/base/tests/e2e/specs/search-params.cy.js b/packages/react-router/test/base/tests/e2e/specs/search-params.cy.js new file mode 100644 index 0000000000..83252c871c --- /dev/null +++ b/packages/react-router/test/base/tests/e2e/specs/search-params.cy.js @@ -0,0 +1,88 @@ +describe('Search Params Navigation', () => { + beforeEach(() => { + cy.visit('/search-params'); + // Wait for the page to be visible + cy.get('[data-pageid="search-params"]').should('be.visible'); + }); + + it('should navigate when adding search params to the same path', () => { + // Verify we start without search params + cy.get('#current-path').should('have.text', '/search-params'); + cy.get('#query-value').should('have.text', ''); + + // Click to add search param - this navigates from /search-params to /search-params?q=test + cy.get('#add-search').click(); + + // The URL should update with the search param + cy.location('pathname').should('eq', '/search-params'); + cy.location('search').should('eq', '?q=test'); + + // The component should re-render with the new search param value + cy.get('#current-path').should('have.text', '/search-params?q=test'); + cy.get('#query-value').should('have.text', 'test'); + }); + + it('should navigate when changing search params on the same path', () => { + // First add a search param + cy.get('#add-search').click(); + cy.get('#query-value').should('have.text', 'test'); + + // Now change the search param + cy.get('#change-search').click(); + + cy.location('search').should('eq', '?q=changed'); + cy.get('#current-path').should('have.text', '/search-params?q=changed'); + cy.get('#query-value').should('have.text', 'changed'); + }); + + it('should navigate when removing search params from the same path', () => { + // First add a search param + cy.get('#add-search').click(); + cy.get('#query-value').should('have.text', 'test'); + + // Now remove the search param + cy.get('#remove-search').click(); + + cy.location('search').should('eq', ''); + cy.get('#current-path').should('have.text', '/search-params'); + cy.get('#query-value').should('have.text', ''); + }); + + it('should restore search params when navigating back from another page', () => { + // Add search param + cy.get('#add-search').click(); + cy.get('#query-value').should('have.text', 'test'); + cy.location('search').should('eq', '?q=test'); + + // Navigate to home page + cy.get('#go-home').click(); + cy.get('[data-pageid="home"]').should('be.visible'); + cy.location('pathname').should('eq', '/'); + + // Go back - should restore /search-params?q=test + cy.go('back'); + cy.get('[data-pageid="search-params"]').should('be.visible'); + cy.location('pathname').should('eq', '/search-params'); + cy.location('search').should('eq', '?q=test'); + cy.get('#query-value').should('have.text', 'test'); + }); + + it('should support back through multiple search param changes', () => { + // Navigate: /search-params -> /search-params?q=test -> /search-params?q=changed + cy.get('#add-search').click(); + cy.get('#query-value').should('have.text', 'test'); + + cy.get('#change-search').click(); + cy.get('#query-value').should('have.text', 'changed'); + + // Go back to ?q=test + cy.go('back'); + cy.location('search').should('eq', '?q=test'); + cy.get('#query-value').should('have.text', 'test'); + + // Go back to no search params + cy.go('back'); + cy.location('search').should('eq', ''); + cy.get('#query-value').should('have.text', ''); + }); +});