Skip to content

fix(iOS, Stack): Fix for reattaching Screens when swiping back quickly#3584

Merged
t0maboro merged 10 commits intomainfrom
@t0maboro/stack-screen-state-mismatch
Feb 2, 2026
Merged

fix(iOS, Stack): Fix for reattaching Screens when swiping back quickly#3584
t0maboro merged 10 commits intomainfrom
@t0maboro/stack-screen-state-mismatch

Conversation

@t0maboro
Copy link
Contributor

@t0maboro t0maboro commented Jan 29, 2026

Description

This PR introduces logic to collect only active (non-dismissed) screen controllers coming from JS state.

When a screen gets dismissed on the native side, its state is sent asynchronously to the JS. In scenarios where multiple screens are dismissed quickly, this can result in stale updates being sent from JS to native. These outdated updates may reference screens that are no longer part of the native view hierarchy.

Since view recycling is disabled, we do not expect the RNSScreenView that was dismissed to be reattached; a new instance should be created when we push an update from JS. Then the new controller instance will be initialized, so these associated with detached screens won't be reused again. Therefore, we can safely filter them out from JS state on the native side. On the JS side, the state will stabilize at some point and align with native, once we receive all asynchronous events.

@implementation RNSScreenView {
...
- (void)initCommonProps
{
  _controller = [[RNSScreen alloc] initWithView:self];

To address this, we now filter out any dismissed controllers from the list received from JS.

Note

I'm leaving the previous behavior as the default, and I'm adding iosPreventReattachmentOfDismissedScreens flag that can enable this fix. We're right before a very important release, and this PR is touching the very basic logic; therefore, we don't want to have this fix enabled by default for now. You can opt-in by setting featureFlags.experiment.iosPreventReattachmentOfDismissedScreens = true. Any feedback would be valuable here.

Closes: #2559

Changes

  • Added an attribute to mark controllers that were dismissed.
  • Added logic for filtering out screens dismissed natively from JS state.

Before & after - visual documentation

Before After
before.mov
after.mov

Test plan

Added Test 2559.

Checklist

  • Included code example that can be used to test this change.
  • Updated / created local changelog entries in relevant test files.
  • For visual changes, included screenshots / GIFs / recordings documenting the change.
  • For API changes, updated relevant public types.
  • Ensured that CI passes

@t0maboro t0maboro marked this pull request as draft January 29, 2026 11:02
@t0maboro t0maboro changed the title WIP - @t0maboro/stack screen state mismatch fix(iOS, Stack): Fix reattaching Screens when swiping back quickly Jan 29, 2026
@t0maboro t0maboro marked this pull request as ready for review January 29, 2026 11:20
@t0maboro t0maboro changed the title fix(iOS, Stack): Fix reattaching Screens when swiping back quickly fix(iOS, Stack): Fix for reattaching Screens when swiping back quickly Jan 29, 2026
@t0maboro t0maboro force-pushed the @t0maboro/stack-screen-state-mismatch branch from fcec68e to e0ce715 Compare January 29, 2026 14:06
Copy link
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, just as we talked. I have one question though, leaving it below 👇🏻

@t0maboro t0maboro requested a review from kkafar January 29, 2026 16:31
Copy link
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this change impacts rather core & crucial functionality of stack, I'd like it to be put behind a feature flag or delay its rollout, especially that we plan to release a next version soon & it might potentially end up in SDK 55. By allowing to control this change through JS we'll allow to patch it much more easily.

I'd suggest adding a "experiment" feature flag, e.g. iosPreventReattachmentOfDismissedScreens and consume it directly on screenstack component.

We can make this flag a noop in two or three minor versions, but next minor should be possibly stable.

What do you think?

@t0maboro
Copy link
Contributor Author

Since this change impacts rather core & crucial functionality of stack, I'd like it to be put behind a feature flag or delay its rollout, especially that we plan to release a next version soon & it might potentially end up in SDK 55. By allowing to control this change through JS we'll allow to patch it much more easily.

I'd suggest adding a "experiment" feature flag, e.g. iosPreventReattachmentOfDismissedScreens and consume it directly on screenstack component.

We can make this flag a noop in two or three minor versions, but next minor should be possibly stable.

What do you think?

8e0f9b3 + c6e5f1c

@t0maboro t0maboro requested a review from kkafar January 30, 2026 12:30
Copy link
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could consider clearing the state in didMoveToParentViewController in case the controller is reattached. Beside that, looks good.

@t0maboro
Copy link
Contributor Author

t0maboro commented Feb 2, 2026

We could consider clearing the state in didMoveToParentViewController in case the controller is reattached. Beside that, looks good.

c9e923b

@t0maboro t0maboro merged commit 0d88498 into main Feb 2, 2026
9 checks passed
@t0maboro t0maboro deleted the @t0maboro/stack-screen-state-mismatch branch February 2, 2026 10:35
OnSpaceAI pushed a commit to OnSpaceAI/expo that referenced this pull request Feb 9, 2026
…fault (expo#43001)

# Why

The fix
software-mansion/react-native-screens#3584 was
merged to react-native-screens, but can only be activated via feature
flag.

See
https://exponent-internal.slack.com/archives/C08RP2QSZPS/p1770035259877429
for more details

# How

<!--
How did you build this feature or fix this bug and why?
-->

# Test Plan

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)

---------

Co-authored-by: Hassan Khan <hassan@expo.dev>
Ubax added a commit to expo/expo that referenced this pull request Feb 10, 2026
…fault (#43001)

# Why

The fix
software-mansion/react-native-screens#3584 was
merged to react-native-screens, but can only be activated via feature
flag.

See
https://exponent-internal.slack.com/archives/C08RP2QSZPS/p1770035259877429
for more details

# How

<!--
How did you build this feature or fix this bug and why?
-->

# Test Plan

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)

---------

Co-authored-by: Hassan Khan <hassan@expo.dev>
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.

[iOS] Unexpected Navigation Behavior When Swiping Back Quickly

2 participants