Hi! 👋
Firstly, thanks for your work on this project! 🙂
Today I used patch-package to patch react-native-multiple-modals@3.3.0 for the project I'm working on.
Here is the diff that solved my problem:
diff --git a/node_modules/react-native-multiple-modals/android/src/main/java/com/multiplemodals/RNTModalView.kt b/node_modules/react-native-multiple-modals/android/src/main/java/com/multiplemodals/RNTModalView.kt
index 3c1f84f..547753a 100644
--- a/node_modules/react-native-multiple-modals/android/src/main/java/com/multiplemodals/RNTModalView.kt
+++ b/node_modules/react-native-multiple-modals/android/src/main/java/com/multiplemodals/RNTModalView.kt
@@ -162,7 +162,7 @@ class RNTModalView(context: Context): ViewGroup(context), LifecycleEventListener
return modalView.childCount
}
- override fun getChildAt(index: Int): View {
+ override fun getChildAt(index: Int): View? {
return modalView.getChildAt(index)
}
diff --git a/node_modules/react-native-multiple-modals/ios/Library/RNTModalViewController/RNTModalViewController.m b/node_modules/react-native-multiple-modals/ios/Library/RNTModalViewController/RNTModalViewController.m
index d581919..e31f85a 100644
--- a/node_modules/react-native-multiple-modals/ios/Library/RNTModalViewController/RNTModalViewController.m
+++ b/node_modules/react-native-multiple-modals/ios/Library/RNTModalViewController/RNTModalViewController.m
@@ -22,6 +22,8 @@
}
- (void)setupReactSubview:(UIView *)subview {
+ if (!self.reactSubviewContainer || !self.view) return;
+
[self.view addSubview:self.reactSubviewContainer];
self.reactSubviewContainer.translatesAutoresizingMaskIntoConstraints = NO;
@@ -65,16 +67,23 @@
- (void)dismiss {
UIView *prevReactSubviewContainer = self.reactSubviewContainer;
- self.reactSubviewContainer = [self.reactSubviewContainer snapshotViewAfterScreenUpdates:NO];
- [prevReactSubviewContainer removeFromSuperview];
-
- [self setupReactSubview:self.reactSubviewContainer];
- [self.outAnimation prepareAnimation:self.reactSubviewContainer];
- [self.outAnimation animate:self.reactSubviewContainer completion:^(BOOL finished) {
+ UIView *snapshot = [self.reactSubviewContainer snapshotViewAfterScreenUpdates:NO];
+
+ if (snapshot) {
+ self.reactSubviewContainer = snapshot;
+ [prevReactSubviewContainer removeFromSuperview];
+ [self setupReactSubview:self.reactSubviewContainer];
+ [self.outAnimation prepareAnimation:self.reactSubviewContainer];
+ [self.outAnimation animate:self.reactSubviewContainer completion:^(BOOL finished) {
+ [self willMoveToParentViewController:nil];
+ [self.view removeFromSuperview];
+ [self removeFromParentViewController];
+ }];
+ } else {
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
- }];
+ }
}
- (void)addReactSubview:(UIView *)view {
This issue body was partially generated by patch-package.
I did used claude opus 4.6 to generate this fix, I'm not a swift developer, so I don't know much about the code it generated in terms of convention and how well the fix is. But it did fix the crash I was having.
*edit
I added additional code for android. The same flow crashed on android and I included the kotlin code.
iOS description:
snapshotViewAfterScreenUpdates:NO in RNTModalViewController's dismiss method returns nil when the view hasn't been rendered at least once (iOS logs: "Snapshotting a view that has not been rendered at least once requires afterScreenUpdates:YES"). This sets self.reactSubviewContainer to nil, and the subsequent call to setupReactSubview: crashes when creating layout constraints with nil anchors:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
Android description:
modalView.getChildAt(index) returns View? (nullable in Android) but the Kotlin override declares the return type as View (non-null). When the child doesn't exist, it crashes with the null assertion.
Steps to reproduce:
- Rapidly open and close multiple ModalView instances (e.g. a modal that triggers a loading modal on submit)
- Repeat 3-5 times (Android crashed after 1 open)
- App crashes on iOS & Android
The fix implemented:
iOS:
- Guard setupReactSubview: against nil reactSubviewContainer or self.view
- In dismiss, check if snapshotViewAfterScreenUpdates: returned nil — if so, skip the animation and dismiss immediately
File: ios/Library/RNTModalViewController/RNTModalViewController.m
Android:
- Change getChildAt return type from View to View? to handle null child during rapid unmount
Files: RNTModalView.kt
Hi! 👋
Firstly, thanks for your work on this project! 🙂
Today I used patch-package to patch
react-native-multiple-modals@3.3.0for the project I'm working on.Here is the diff that solved my problem:
This issue body was partially generated by patch-package.
I did used claude opus 4.6 to generate this fix, I'm not a swift developer, so I don't know much about the code it generated in terms of convention and how well the fix is. But it did fix the crash I was having.
*edit
I added additional code for android. The same flow crashed on android and I included the kotlin code.
iOS description:
snapshotViewAfterScreenUpdates:NOinRNTModalViewController'sdismissmethod returnsnilwhen the view hasn't been rendered at least once (iOS logs:"Snapshotting a view that has not been rendered at least once requires afterScreenUpdates:YES"). This setsself.reactSubviewContainertonil, and the subsequent call tosetupReactSubview: crashes when creating layout constraints withnilanchors:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
Android description:
modalView.getChildAt(index) returns View? (nullable in Android) but the Kotlin override declares the return type as View (non-null). When the child doesn't exist, it crashes with the null assertion.
Steps to reproduce:
The fix implemented:
iOS:
File: ios/Library/RNTModalViewController/RNTModalViewController.m
Android:
Files: RNTModalView.kt