Skip to content

Fix blank page when the app rerenders during logout - #11435

Merged
fzaninotto merged 1 commit into
masterfrom
fix/stable-internal-router
Nov 1, 2026
Merged

fzaninotto merged 1 commit into
masterfrom
fix/stable-internal-router

Conversation

@fzaninotto

Copy link
Copy Markdown
Member

Problem

Fixes #11431

InternalRouter calls createHashRouter in its render body, so every rerender of the component rendering <Admin> discards the router and creates a new one at the current URL. A navigation scheduled on the previous router then updates the URL without the current router ever seeing it: the URL becomes #/login but the page stays blank.

This happens whenever something above <Admin> rerenders while authProvider.logout() runs - a common pattern with auth SDKs, which notify a context provider when the session is cleared.

Router state that does not live in the URL is lost the same way. A navigation blocked by useBlocker (the "unsaved changes" guard) silently disappears when the parent rerenders.

Solution

Create the router once.

The router keeps the route element it was created with, so that element can no longer close over the children, or the whole tree under <Admin> would be frozen at its first render (dynamic resources, routes behind permissions, anything passed down from above <Admin> would stop updating). It now reads the children from a context placed above the RouterProvider, so children updates still reach the router.

The basename can only be set when the router is created, so RouterWrapper remounts InternalRouter when it changes. A basename change therefore recreates the router, as before - but a plain rerender no longer does.

How To Test

yarn test-unit packages/ra-core/src/routing/adapters

The three tests each fail without the corresponding part of the fix:

  • should not lose the navigation state when the parent rerenders - a navigation blocked by useBlocker survives a parent rerender
  • should rerender the children when the parent rerenders - the tree under <Admin> still receives updates
  • should take the new basename into account when it changes

The blank page from the issue itself only reproduces with React 19 and react-router 7, so it is not covered by a unit test here; it was verified manually with the issue's reproduction (react-admin built from this branch, React 19.3.1, react-router 7.18.4): the login page now renders instead of a blank page.

Additional Checks

  • The PR targets master for a bugfix or a documentation fix, or next for a feature
  • The PR includes unit tests (if not possible, describe why)
  • The PR includes one or several stories (not applicable: internal router lifecycle, no visual surface)
  • The documentation is up to date (no documentation change required)

🤖 Generated with Claude Code

InternalRouter called createHashRouter in its render body, so every
rerender of the component rendering <Admin> discarded the router and
created a new one at the current URL. A navigation scheduled on the
previous router then updated the URL without the current router ever
seeing it, leaving a blank page - typically when an auth SDK notifies
the app that the session was cleared while authProvider.logout() runs.
Router state that does not live in the URL, such as a navigation
blocked by useBlocker, was lost the same way.

The router is now created once. As it keeps the route element it was
created with, that element reads the children from a context instead of
closing over them, so children updates still reach the router. The
basename can only be set at creation time, so RouterWrapper remounts
InternalRouter when it changes.

Closes #11431

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@fzaninotto fzaninotto mentioned this pull request Nov 1, 2026
3 of 4 tasks
@fzaninotto
fzaninotto merged commit 232d8e3 into master Nov 1, 2026
15 checks passed
@fzaninotto
fzaninotto deleted the fix/stable-internal-router branch November 1, 2026 18:55
@fzaninotto fzaninotto added this to the 5.15.6 milestone Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blank page after logout when the app re-renders <Admin> during authProvider.logout()

1 participant