Skip to content

fix(react-router): show pages swapped into one view - #31526

Open
djoume wants to merge 1 commit into
ionic-team:mainfrom
djoume:fix/react-router-single-view-reveal
Open

djoume wants to merge 1 commit into
ionic-team:mainfrom
djoume:fix/react-router-single-view-reveal

Conversation

@djoume

@djoume djoume commented Oct 2, 2026

Copy link
Copy Markdown

Issue number: resolves #31525


What is the current behavior?

When an outlet's only route is a splat whose element renders <Routes>, every navigation swaps a new IonPage into the same view item. Each new page mounts with ion-page-invisible. isDuplicateTransition compares only the entering and leaving view ids, so the swap looks like a repeat of the previous transition and is skipped. The page stays at opacity: 0, which leaves a blank screen. This happens:

  • from the second root navigation on, with path="/*";
  • from the second navigation of any kind, with a bare path="*".

What is the new behavior?

  • lastTransition also records the entering IonPage element, and a transition only counts as a duplicate when that element is the same too. A newly mounted page now takes the normal transitionPage path, so it is revealed and fires its lifecycle events. A second call for the same navigation, with the same element, is still skipped.
  • Adds a root-single-view test app, served under its own basename like root-splat-sibling, and root-single-view.spec.ts:
    • with /*: three root navigations each leave the target page visible;
    • with a bare * (?splat=bare): three pushes each leave the target page visible.

Does this introduce a breaking change?

  • Yes
  • No

Other information

  • The new spec fails at the second navigation without the StackManager change, and passes with it.
  • With the change, reactrouter6-react18 passes the full Playwright suite (127/127) and the full Cypress suite (206/206). npm run typecheck and npm run lint are clean.
  • An earlier version revealed the page with an early return for same-view swaps. It broke tab-lifecycle.spec.ts (FW-6788), because returning tabs need transitionPage to fire ionViewDidEnter. Fixing the duplicate check keeps that path.

An outlet whose single route renders a plain <Routes> keeps one view
item and swaps a new IonPage into it on every navigation. Each new page
mounts with ion-page-invisible, but the duplicate-transition guard only
compared view ids, so from the second root navigation (or the second
push under a bare "*" route) the transition was skipped and the page
stayed invisible. Compare the entering IonPage element as well, so a
newly mounted page gets its transition, reveal and lifecycle events.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@djoume
djoume requested a review from a team as a code owner October 2, 2026 22:51
@djoume
djoume requested a review from ShaneK October 2, 2026 22:51
@vercel

vercel Bot commented Oct 2, 2026

Copy link
Copy Markdown

@djoume is attempting to deploy a commit to the Ionic Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the package: react @ionic/react package label Oct 2, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: react @ionic/react package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: (react-router): page stays ion-page-invisible after root navigations when the outlet holds a single splat view

1 participant