Skip to content

fix(blank-stack): render the fresh descriptor when route params change - #159

Open
ptrnk0 wants to merge 1 commit into
eds2002:mainfrom
ptrnk0:fix/blank-stack-stale-descriptor-on-params-change
Open

ptrnk0 wants to merge 1 commit into
eds2002:mainfrom
ptrnk0:fix/blank-stack-stale-descriptor-on-params-change

Conversation

@ptrnk0

@ptrnk0 ptrnk0 commented Oct 16, 2026

Copy link
Copy Markdown

Motivation

Fixes #158.

When only a BlankStack route's params change, buildBaseScenes keeps the previous descriptor source as long as the child state is unchanged and the options are shallow-equal (areDescriptorSourcesEquivalent compares only options). The scene's render comes from that source, and React Navigation's render closes over the route it was created with — so the screen keeps rendering the old route.

The most visible symptom is deep links: React Navigation delivers a link into a nested navigator as params on the parent route ({ screen, params, ... }), and the nested navigator only reacts once it sees them. With a BlankStack in between it never does, so links into nested stacks silently stay on the current screen. Any navigate/setParams that changes params of a mounted BlankStack screen without changing its options is affected the same way.

Change

Reuse the stable descriptor source only when the route itself is also shallow-equal to the previous one. Params-only changes now take the fresh descriptor (and its render); re-renders with an equivalent route keep the existing stability — the existing "skips state updates for fresh equivalent route descriptors" test still passes unchanged.

Test plan

  • New test renders with the fresh descriptor when only route params change in blank-stack-controller.test.ts — fails on main, passes with this change.
  • bun test — 477 pass, 0 fail
  • bun run lint — clean
  • bun run typecheck — clean
  • Verified in a production Expo SDK 57 / RN 0.86 app (via patch-package on 4.0.0): external links into a nested Stack under a BlankStack navigate correctly again. Not run: the Maestro e2e suite.

🤖 Generated with Claude Code

buildBaseScenes reused the previous descriptor source whenever the
route's child state was unchanged and its options were shallow-equal.
That source's render closes over the route it was created with, so a
params-only change (e.g. a deep link targeting a nested navigator) kept
rendering the old route and the nested navigator never saw
`params.screen`. Reuse the stable source only when the route itself is
also shallow-equal.

Fixes eds2002#158

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@netlify

netlify Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for rnst-docs ready!

Name Link
🔨 Latest commit acd144c
🔍 Latest deploy log https://app.netlify.com/projects/rnst-docs/deploys/6ad243d7c40cae0c0336feec
😎 Deploy Preview https://deploy-preview-159--rnst-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ptrnk0

ptrnk0 commented Oct 19, 2026

Copy link
Copy Markdown
Author

Reproduction for the bug this PR fixes (#158 was auto-closed and locked before I could add it): https://github.com/ptrnk0/screen-transitions-deeplink-repro

Expo SDK 57 + [email protected]. Runs in Expo Go. A BlankStack root hosts a group with a regular Stack (index, settings). With the app open on index, run xcrun simctl openurl booted "exp://127.0.0.1:8083/--/settings".

Verified on an iOS simulator:

  • BlankStack root on 4.0.0: the link does nothing.
  • Plain Stack root: the link pushes settings.
  • BlankStack root with this PR's change applied: the link pushes settings.

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.

[Bug]: Blank Stack keeps rendering a stale route when only route params change (breaks deep links into nested navigators)

1 participant