react-native: ios: cannot dismiss Modal

Please provide all the information requested. Issues that do not follow this format are likely to stall.

Description

When modal is dismissed the whole screen turns black. see video

React Native version:

System:
    OS: macOS 11.6
    CPU: (8) x64 Apple M1
  Binaries:
    Node: 14.15.4 - /usr/local/bin/node
    npm: 7.6.3 - /usr/local/bin/npm
    Watchman: 4.9.0 - /opt/homebrew/bin/watchman
  IDEs:
    Android Studio: Not Found
    Xcode: 13.0/13A233 - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_302 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.2 => 17.0.2
    react-native: ~0.66.0 => 0.66.0
    react-native-macos: Not Found

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. use this code with react native 0.66 on iOS

video

RCTModalHostViewController is what’s blocking the screen Screenshot 2021-10-04 at 6 54 47 pm

Screenshot 2021-10-04 at 6 49 43 pm .

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 29
  • Comments: 68 (1 by maintainers)

Most upvoted comments

Another update – Here’s what I ended up doing:

<View style={{flex: 1}}>
    <Modal visible={isVisible}></Modal>
</View>

This seemed to work, though I’m not sure why wrapping it with a View with flex: 1 is needed 🤔

I also then noticed that if I have multiple modals on the same page, this issue is only fixed for the first one (likely because of the flex: 1). So I updated the code to be

{isFirstModalVisible && (
    <View style={{flex: 1}}>
        <Modal visible={isFirstModalVisible}></Modal>
    </View>
)}

{isSecondModalVisible && (
    <View style={{flex: 1}}>
        <Modal visible={isSecondModalVisible}></Modal>
    </View>
)}

That way the modals are only rendered when visible, and there’s only 1 modal on a page at a time.

This has solved my issue for now, but I wish I didn’t have to do all this. Really hoping this issue is looked into.

Hello, Version 2.2.3 of react-reanimated seems to fix the issue on our side. Regards

Oh god, I’m so happy. I can confirm that my issues are gone as well, both modal dismiss and “zombie” screens… Thanks for letting us know @littleski! ❤️

A temporary workaround (that worked for me) without having to downgrade anything, i.e. it works with the following:

...
"react-native": "0.66.0",
"react-native-reanimated": "^2.3.0-beta.2",
...

is to disable the autoinstall of Reanimated (during compilation) in your Podfile per their own documentation here

post_install do |installer|
   installer.pods_project.targets.each do |target|
       target.build_configurations.each do |config|
           config.build_settings['OTHER_CPLUSPLUSFLAGS'] = '-DDONT_AUTOINSTALL_REANIMATED'
       end
   end
end

Remember to pod install after changing the Podfile

This allowed my setup to compile and run normally without experiencing the zombie UITransitionView after dismissing a modal.

side note

$0.02: I’m not convinced that the problem lies strictly within react-native-reanimated itself, but is manifest when some magic combination of react-native, react-native-screens, @react-navigation/*, and react-native-reanimated alter the native view hierarchy (UIKit) or inject event blocks that cause some async problems/race condition.

Additionally, a cursory search (google/SO) for UITransitionView has hits for “stuck” views going back 5+ years.

The latest versions of RN and Reanimated may have just “tickled” an old UIKit bug… 🤷

A workaround that I dislike but that seems to fix the issue for me is to mount/unmount the modal instead of using the visible prop 😢

<>
  {modalVisible && <Modal visible><Content /></Modal>}
</>

Having the same issue with Modals. After a modal is closed, the rest of the app becomes unresponsive and needs to be closed and reopened.

You guys can try by going to the file Pods/Development Pods/React-Core/Default/Views/RCTModalHostView and inside the method dismissModalViewController,

add the following lines: dispatch_async(dispatch_get_main_queue(), ^{ [_delegate dismissModalHostView:self withViewController:_modalViewController animated:[self hasAnimationType]]; _isPresented = NO; });

well, passing coverScreen={false} prop for react-native-modal seems to be a workaround for this as well, thanks for the help

Have the same issue using @react-navigation/stack. When we navigate to next stack screen and then go back, a transparent “view” blocks any interaction.

Having the same problem.

issue still exists with react-native: 0.66.3 and react-native-reanimated: 2.2.3 it works after dropping some animation code I was using

if (!IS_IOS && UIManager.setLayoutAnimationEnabledExperimental) {
   UIManager.setLayoutAnimationEnabledExperimental(true);
 }

LayoutAnimation.configureNext(
                  LayoutAnimation.create(
                    300,
                     LayoutAnimation.Types.easeInEaseOut,
                     LayoutAnimation.Properties.opacity,
                   ),
     );

any ideas why this is happening.

System:
    OS: macOS 12.0.1
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 27.55 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 12.22.7 - ~/.nvm/versions/node/v12.22.7/bin/node
    Yarn: 1.22.17 - ~/.nvm/versions/node/v12.22.7/bin/yarn
    npm: 7.22.0 - ~/.nvm/versions/node/v12.22.7/bin/npm
    Watchman: 2021.11.08.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.11.2 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.0.1, iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0
    Android SDK:
      API Levels: 23, 28, 29, 30, 31
      Build Tools: 29.0.2, 30.0.2, 31.0.0
      System Images: android-30 | Google Play Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: Arctic Fox 2020.3.1 Patch 3 Arctic Fox 2020.3.1 Patch 3
    Xcode: 13.1/13A1030d - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_292 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: ^17.0.2 => 17.0.2 
    react-native: 0.66.3 => 0.66.3 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

edited

I have a similar issue. My screen didn’t turn black, but the entire app becomes unresponsive. Upgraded from RN 0.64.2 to 0.66, literally no other packages changed. Unable to reproduce on Android. iOS only.

I tried out the Modal component as part of the React Native standard library, also react-native-modal and react-native-paper’s modal - they all had this same behaviour. I believe they are all wrapped versions of Modal from RN?

Another update – Here’s what I ended up doing: […]

{isFirstModalVisible && (
    <View style={{flex: 1}}>
        <Modal visible={isFirstModalVisible}></Modal>
    </View>
)}

Thanks! I had to change them from flex: 1 to flex: 0 since I already had a flex: 1 child component (with a flex: 1 parent component) that was intended to fill the whole screen and not share the space with any modals

EDIT: Modals that appear in succession seem to be broken with 2.3.0-beta.2 + RN 0.66.0, even when using this solution (as well as when not using it): any modal that appears immediately after another does not appear.

EDIT2: I ended up just completely deleting this library from my 0.66.0 app as @supervons said, and everything seems to work as intended (in iOS, at least). I don’t think this library has any noticeably useful purpose for my app whatsoever: just adds more possibilities for bugs.

I just encountered this on an upgrade from 0.64.1 -> 0.66.0 (iOS 11 - 15 simulator). Traced it down to a 3rd party component that is using a transparent Modal under the hood.

In this case it’s even more insidious since the modal is set as transparent; Once displayed the modal’s view never dismisses, and it swallows all touch events on the entire screen rendering the app effectively frozen.

An experimental attempt to pass through a pointerEvents: 'box-none' prop had no effect as a workaround.

However, When in the simulator AND debugging (w/chrome; flipper is not enabled in my project) is active, the Modal dismisses properly.

Yep, facing the same issue. I am on react-native version 0.65.1

Just bumped into this while reading react-navigation documentation 😅 Although this is for drawer navigator, I’m assuming it applies to others as well. So it makes sense why it works with Chrome debugger… image

(cc: @dotansimha @NoerNova)

react-native-reanimated@2.2.3 worked for me with React Native 0.66 🎉 Previously only the 2.3.x beta supported RN 0.66 but 2.3.0-beta.2 / 2.3.0-beta.3 do not work on iOS currently.

@Dmitry-GH I’m not super familiar with the internals of Reanimated, but I believe it provides (at least) 2 main features for developers:

  • A more expressive, pure JavaScript (syntax vs. JSX) API for scripting animations/animated behaviors
  • The ability to ensure animations are calculated and executed on a native thread; so interpolations would be calculated on the native side as opposed to on the JS VM side and then having to sync over the bridge back into native (potentially several times per second). Pushing the animation stuff into native frees things up to handle events (touch) and trigger UI changes in a timely fashion.

With that, library and component authors can leverage the Reanimated lib to make things visually smooth and performant when there are complex UI transformations/layering/gesture effects, etc…

The potential downside to disabling the compiled code might be visual/performance issues in certain situations. They emphasize animations in response to gestures.

(Speculation) I would imagine that most of the mainstream dependent libraries conditionally depend on reanimated so disabling it will probably fall-back to regular RN behavior.

Not sure what happens if you’ve coded against Reanimated’s API directly…no op perhaps…

Anyway, I’m not all that familiar with the implementation.

They have a good description of what purpose Reanimated serves over here

I think this issue occurs when upgrading react-native-reanimated to 2.3.0-beta.2 which is (as of now) the only version that works on RN 0.66. When I downgraded from RN 0.66.0 to 0.65.1, the modal issue was still there. It disappeared only after downgrading react-native-reanimated.

I will be attempting to reproduce this in a clean project and reporting it to the Reanimated repo. Edit: it has been reported already, my bad.

Screen freezing on a couple of situations for me,

  • Modal (react-native) -> no issue on react-native-paper’s Modal
  • FlatList and Animated.Flatlist on re-render, reload -> {flex: 1} on parent not help.

BTW. all stuff works fine with opening debugging mode (Debug with Chrome) 🧐

I have a similar issue. My screen didn’t turn black, but the entire app becomes unresponsive. Upgraded from RN 0.64.2 to 0.66, literally no other packages changed. Unable to reproduce on Android. iOS only.

I tried out the Modal component as part of the React Native standard library, also react-native-modal and react-native-paper’s modal - they all had this same behaviour. I believe they are all wrapped versions of Modal from RN?

Same here. Upgraded to RN66 and since than we had freezing with react-native-modal, react-native-screens and react-navigation@6. If I turn on Debug in Chrome DevTools on the app - everything seems to work perfectly fine 🤔 I guess it might be related to Flipper?

With react-native-modal -> happens with all modals With react-navigation / react-native-screens -> happens with Stack navigator that has FlatList (that loads additional data using pagination, after loading more items and going back -> screen freezes, seems like there are two RNSScreen in view, one is a zombie view that contains a ScrollView)

Same here! react-native-reanimated@2.2.3 fixes the issues!

I can confirm that updating to react-native-reanimated@2.2.3 fixes this issue.

I tried the workaround but unfortunately, when you don’t install Reanimated and you use Animated component it doesn’t work. I use BottomTabBar from react-navigation (I have v4) and there is CrossFadeIcon component which creates Animated.View.

When I applied the workaround, my app crashes on the start due to some InnerNativeModule variable inside reanimated library being undefined.

I had similar issue, but I’m using react-native-modal. After dismissing, the Modal also changed to transparent and only found it thanks to Xcode’s “Debug View Hierarchy”… Also I was upgrading from 0.64.0 to 0.66.0.

I’m having this issue in both debug and release, though. Happens on iOS 15 Simulator (debug), iPhone 12 mini (release) and iPhone 6S (release).

I didn’t try debugging with Chrome because it causes my app to instantly crash and I have to reinstall it to even disable debugger 😅 But it’s possible it’s some kind of race condition, as Chrome decreases performance (I think).

@effektsvk yeah, i checked with the debug view hierarchy and it’s exactly RCTModalHostViewController on top of everything, i already have 2.3.0-beta3 that include the workaround but seems not had not effect.

image

Same issue , i removed react-native-reanimated, everything works.

With react-native-modal -> happens with all modals With react-navigation / react-native-screens -> happens with Stack navigator that has FlatList (that loads additional data using pagination, after loading more items and going back -> screen freezes, seems like there are two RNSScreen in view, one is a zombie view that contains a ScrollView)

Yes, I’m having this as well, I wasn’t sure if it was related, because the RNSScreen comes from react-native-screens but the behavior is very similar.

I was trying to debug it in Xcode and it seems that there is logic which destroys that RNSScreen view when screen is inactive, but according to my debugging, it looks like the screen is in TransitioningOrBelowTop state right after I click the back button. I also confirmed that the “zombie view” is the one I was backing from. I could also create multiple zombie views by dispatching navigation actions (I’m using react-navigation@4 with Redux state) and every time I navigated back it created a new dead screen.

(cc: @dotansimha)

I can confirm this is exactly the issue we’re having. And if Flipper is not the active debugger it works fine,

With react-native-modal -> happens with all modals With react-navigation / react-native-screens -> happens with Stack navigator that has FlatList (that loads additional data using pagination, after loading more items and going back -> screen freezes, seems like there are two RNSScreen in view, one is a zombie view that contains a ScrollView)

Yes, I’m having this as well, I wasn’t sure if it was related, because the RNSScreen comes from react-native-screens but the behavior is very similar.

I was trying to debug it in Xcode and it seems that there is logic which destroys that RNSScreen view when screen is inactive, but according to my debugging, it looks like the screen is in TransitioningOrBelowTop state right after I click the back button. I also confirmed that the “zombie view” is the one I was backing from. I could also create multiple zombie views by dispatching navigation actions (I’m using react-navigation@4 with Redux state) and every time I navigated back it created a new dead screen.

(cc: @dotansimha)

Same issue happened with me after upgrading to RN 0.66, react-native-picker-select library (which uses Modal under the hood) freezes the whole app.

Hey! For me, it looks like the problem is in “react-native-reanimated” lib. I downgraded it for now to fix it. Details: software-mansion/react-native-reanimated#2244 (comment)

This sadly won’t work for RN 0.66

Yes, because reanimated 2.2.2 won’t work with RN 0.66. That’s why in my solution I’v downgraded them both.

confirming this on RN 0.65.1

Chrome debugging doesn’t work for me, so I’m unable to check, unfortunately. I’m unable to get into the app when the debugger is enabled, I need to reinstall the app to use it again.