react-native-screens icon indicating copy to clipboard operation
react-native-screens copied to clipboard

IOS Modal causing glitches and crashs when using exiting animation inside it

Open YasinAkimura opened this issue 11 months ago • 18 comments

Description

description is not missing *test

related to

  • (maybe) https://github.com/software-mansion/react-native-screens/issues/2454
  • https://github.com/expo/expo/issues/32940

INFO: copied from my issue on expo-router repo as its still the same

  • read the crash report below and you'll see it's related to react-native-screens
  • only happens on iOS
  • you really need to use a custom header doesn't matter what kind of when it's there it'll crash if screen contains a view with exiting animation
  • seems to be new arch related did not happen before so I had to temporary remove all exiting animations and or modals in my project to continue trying out the new arch

Expected Behavior

I can dismiss the modal containing any basic headers configured in screenOptions and I should be able to use functionalities which are not marked as unstable or experimental like exiting animations on reanimated.

Whats actually happening

App and Modal screen glitches completely out after swiping it down a few times.

  • Note: You don't even have to do it as fast as I did on the provided video.

I am also sure that this bug is different from https://github.com/expo/expo/issues/32874#issuecomment-2477988050 as react-native-screens does not fix that issue and the cause is precise problem.

  • Did not happen on previous SDK eg old arch and react-native-screens < 4
  • I think that issue is related to reanimated and ~~expo-router eg. react-navigation~~ react-native-screens.
  • What's weird is that the cause is so specific ONLY IF you use a custom header and happen to have an exiting animation on any component in that modal it glitches out so it might be connected.
updated video

https://github.com/user-attachments/assets/d8842d5b-1e1a-4e81-b465-d359794ee3dc

Bildschirmfoto 2024-12-11 um 12 51 37

crash report

[Foundation] *** Assertion failure in -[RNSScreenStackView setModalViewControllers:](),
/Users/yasinsimsek/Projects/ExpoSDK52-Modal-issue/node_modules/react-native-screens/ios/RNSScreenStack.mm:452
[CoreFoundation] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modally presented controllers are
being reshuffled, this is not allowed'
*** First throw call stack:
(
0   CoreFoundation                      0x00000001804b757c __exceptionPreprocess + 172
1   libobjc.A.dylib                     0x000000018008eda8 objc_exception_throw + 72
2   Foundation                          0x0000000180e7a398 -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0
3   ExpoSDK52Modalissue.debug.dylib     0x0000000108e33d8c -[RNSScreenStackView setModalViewControllers:] + 1712
4   ExpoSDK52Modalissue.debug.dylib     0x0000000108e35de0 -[RNSScreenStackView updateContainer] + 1208
5   ExpoSDK52Modalissue.debug.dylib     0x0000000108e34588 __46-[RNSScreenStackView setModalViewControllers:]_block_invoke + 220
6   ExpoSDK52Modalissue.debug.dylib     0x0000000108e34e14 __46-[RNSScreenStackView setModalViewControllers:]_block_invoke_2 + 144
7   UIKit                               0x0<…>

Steps to reproduce

  1. create a modal screen on ios
  2. put an AnimatedView with exiting animation inside the modal AND use a CUSTOM header (very important)
  3. open and close the modal using swipe / touch gestures and it'll crash on you eventually

Snack or a link to a repository

https://github.com/YasinAkimura/expo-sdk-52-modal-bug-reanimated

Screens version

4.3.0

React Native version

0.76.3

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Expo bare workflow

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

iPhone 16 Pro (iOS 18.1)

Acknowledgements

Yes

YasinAkimura avatar Dec 02 '24 18:12 YasinAkimura

Hey! Thanks for reporting. How is the crash you pasted connected to the recording? I don't see the app crash on the video you provided.

The visual glitches are observable. This looks like some bad interactions between react-native-screens and react-native-reanimated. We'll look into this.

kkafar avatar Dec 11 '24 08:12 kkafar

Hey! Thanks for reporting. How is the crash you pasted connected to the recording? I don't see the app crash on the video you provided.

The visual glitches are observable. This looks like some bad interactions between react-native-screens and react-native-reanimated. We'll look into this.

I also experience this. The bad interactions between react-native-screens and react-native-reanimated also lead to strange animation effects when a modal opens on a iPhone. Strangely this only happens in "production release" not in Dev mode. Maybe you could look into that behavior as well :-) Thx!

jgo80 avatar Dec 11 '24 08:12 jgo80

Hey! Thanks for reporting. How is the crash you pasted connected to the recording? I don't see the app crash on the video you provided.

The visual glitches are observable. This looks like some bad interactions between react-native-screens and react-native-reanimated. We'll look into this.

Ah yes I didn't update the recording that one you saw was with expo-go there it also crashed but after a few more tries then on the simulator it also first left a few broken fragments of the modal at the bottom of the screen with the app not responding properly and then crashing.

*updated the video and provided a screenshot above

YasinAkimura avatar Dec 11 '24 11:12 YasinAkimura

Thanks for the update!

kkafar avatar Dec 11 '24 13:12 kkafar

I also experience this. The bad interactions between react-native-screens and react-native-reanimated also lead to strange animation effects when a modal opens on a iPhone. Strangely this only happens in "production release" not in Dev mode. Maybe you could look into that behavior as well :-) Thx!

I have the same issue in dev mode and old architecture.

bnemeth-parkl avatar Dec 16 '24 09:12 bnemeth-parkl

I have to revise my statement, for me it also happens both in dev mode and release mode.

jgo80 avatar Dec 16 '24 09:12 jgo80

I forwarded the issue to reanimated team

kkafar avatar Dec 17 '24 12:12 kkafar

Same thing happens for me. Hadn't seen it until I tried using my app on a physical device. Also happens after creating a build and running it on my simulator. Here's the full trace. Screenshot 2024-12-17 at 17 13 20

thomasflensted avatar Dec 17 '24 16:12 thomasflensted

I forwarded the issue to reanimated team

Is there a reference, or a new issue or will updates be posted here? Thx for looking into this 🙏

jgo80 avatar Jan 06 '25 13:01 jgo80

Hello do we have any updates on this? I am still facing this issue

Splanis avatar May 09 '25 09:05 Splanis

Hey guys, how are you?

Do we have an update on this? I'm experiencing the same issue, if the user opens and closes the modal too fast the app crashes.

https://github.com/user-attachments/assets/4a619033-5c5d-4df8-a268-68ce82562f25

muriloalvestravelpass avatar May 13 '25 15:05 muriloalvestravelpass

@kkafar have you created an issue on reanimated team repo? If you did, can you share the link? Please 😄

muriloalvestravelpass avatar May 13 '25 15:05 muriloalvestravelpass

I can confirm that the issue happens when

  • NOT having headerShown true
  • having exiting animations on some components
  • presentantion is modal or bottomSheet

I have "react-native-screens": "4.10.0", "react-native-reanimated": "3.17.5", "react-native": "0.76.9"(tested on 0.79 also)

Have anyone tried to find some versions that work ok?

I am trying to migrate from "@react-navigation/stack" (which works fine) to "@react-navigation/native-stack"

Splanis avatar May 14 '25 17:05 Splanis

I'm also affected by this regression.

I'm going to try using this as a workaround, taking advantage of the fact that using the native header for the modal route prevents the crash. This adds the header on iOS, but makes it fully transparent. Tap targets underneath the header won't work, but for my use case it's very unlikely that the user will scroll such that a tap target would be under the transparent header and even if they do that's vastly preferable to the crash.

        <Stack.Screen
          name="MyModal"
          options={{
            presentation: 'modal',
            ...(Platform.OS === 'ios'
              ? {
                  headerShown: true,
                  headerTransparent: true,
                  headerTitle: '',
                }
              : {
                  headerShown: false,
                }),
          }}
          component={MyModalComponent}
        />

tobobo avatar May 23 '25 03:05 tobobo

I'm also affected by this regression.

I'm going to try using this as a workaround, taking advantage of the fact that using the native header for the modal route prevents the crash. This adds the header on iOS, but makes it fully transparent. Tap targets underneath the header won't work, but for my use case it's very unlikely that the user will scroll such that a tap target would be under the transparent header and even if they do that's vastly preferable to the crash.

        <Stack.Screen
          name="MyModal"
          options={{
            presentation: 'modal',
            ...(Platform.OS === 'ios'
              ? {
                  headerShown: true,
                  headerTransparent: true,
                  headerTitle: '',
                }
              : {
                  headerShown: false,
                }),
          }}
          component={MyModalComponent}
        />

good idea but for my case doesnt seem to help. Transparent header won't let my custom header underneath to be pressed :/

Splanis avatar May 28 '25 07:05 Splanis

Hi @YasinAkimura! I prepared a fix in the reanimated repo. Can you check it out?

bartlomiejbloniarz avatar Jun 17 '25 10:06 bartlomiejbloniarz

@bartlomiejbloniarz I will compare it first to ~3.18.0 and the current beta after that I'll apply your changes to see if there are any changes in behavior but it sounds promising as it seems to be the cause

YasinAkimura avatar Jun 17 '25 20:06 YasinAkimura

@bartlomiejbloniarz I can confirm that your PR fixes the issue of this ticket. 3.18.0 did not fix it and the current beta 4.0.0-beta.5 did also not fix it I think ur fix should also be applicable to 3.x versions

YasinAkimura avatar Jun 17 '25 22:06 YasinAkimura

I still find this happening with headerShown: false

Nitrammets avatar Aug 30 '25 23:08 Nitrammets

For those still looking for a solution, the easiest fix is to just disable gesture dismissal:

<Stack.Screen 
  options={{
    presentation: 'modal',
    gestureEnabled: false,
  }}
/>

Azhi-10133 avatar Oct 14 '25 22:10 Azhi-10133

We're seeing something similar in 4.18.0:

  • Open a formSheet modal
  • Close sheet (either by swiping or pressing outside) and quickly interact with the view behind the form sheet
  • The error below happens consistently
- (void)invalidate
{
  _controller = nil;
  [_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil];
}

// Error on _sheetsScrollView row

// Thread 1: "Cannot remove an observer <RNSModalScreen 0x11bae5c00> for the key path \"bounds\" 
// from <RCTScrollViewComponentView 0x11881e9d0> because it is not registered as an observer."

Edit: This was solved in #3356

believer avatar Oct 24 '25 14:10 believer

same issue like "believer" with formSheet but modal is worked.

bare react native

"react-native": "0.82.1",
"react-native-screens": "^4.18.0",
"react-native-reanimated": "^4.1.5",

jordankkk avatar Nov 26 '25 10:11 jordankkk