react-native: iOS: UI will be blocked when show Alert while closing Modal
When show Alert while closing Modal, the Alert dialog will disappear and the Modal will block the UI entirely even after reload, only on iOS.
'use strict';
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
Modal,
Alert,
} from 'react-native';
class demo extends Component {
state = {
showModal: false,
}
onShowModal = () => {
this.setState({ showModal: true });
}
onCloseModal1 = () => {
this.setState({ showModal: false }, () => {
Alert.alert('Alert', 'UI will be blocked by the modal');
});
}
onCloseModal2 = () => {
this.setState({ showModal: false }, () => {
setTimeout(() => {
Alert.alert('Alert', 'Alert won\'t show');
}, 200);
});
}
onCloseModal3 = () => {
this.setState({ showModal: false }, () => {
setTimeout(() => {
Alert.alert('Alert', 'Works fine');
}, 510);
});
}
render() {
const { showModal } = this.state;
return (
<View style={styles.container}>
<Text onPress={this.onShowModal}>Show modal</Text>
<Modal animationType='slide' visible={showModal} onRequestClose={this.onCloseModal3} >
<View style={styles.container}>
<Text onPress={this.onCloseModal1}>Close modal immediately</Text>
<Text onPress={this.onCloseModal2}>Close modal after 200ms</Text>
<Text onPress={this.onCloseModal3}>Close modal after more then 500ms</Text>
</View>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'space-around',
},
});
export default demo;
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 269
- Comments: 184 (46 by maintainers)
Commits related to this issue
- update Modal.js to fix #10662 Summary: further discussion: should there be a `onClose` or `onClosed` to pair with `onShow`? which would make a workaround for #10471 much easier Closes https://github.... — committed to facebook/react-native by nihgwu 8 years ago
- update Modal.js to fix #10662 Summary: further discussion: should there be a `onClose` or `onClosed` to pair with `onShow`? which would make a workaround for #10471 much easier Closes https://github.... — committed to mlguys/react-native by nihgwu 8 years ago
- update Modal.js to fix #10662 Summary: further discussion: should there be a `onClose` or `onClosed` to pair with `onShow`? which would make a workaround for #10471 much easier Closes https://github.... — committed to DanielMSchmidt/react-native by nihgwu 8 years ago
- Avoid presenting on view controller that's being dismissed Summary: Mitigates the issue in https://github.com/facebook/react-native/issues/10471, by not trying to present a modal or alert view if the... — committed to facebook/react-native by javache 7 years ago
- Avoid presenting on view controller that's being dismissed Summary: Mitigates the issue in https://github.com/facebook/react-native/issues/10471, by not trying to present a modal or alert view if the... — committed to thotegowda/react-native by javache 7 years ago
- Change animationType of the modal to 'none' This might fix the pesky freezing issue on iOS. Ref: https://github.com/facebook/react-native/issues/10471 — committed to varunvs/react-native-material-dialog by varunvs 7 years ago
- ActionSheet onDismiss Make use of Modal's `onDismiss` event: [10471](https://github.com/facebook/react-native/issues/10471#issuecomment-280939776) — committed to lodev09/react-native-cell-components by lodev09 6 years ago
- Make Alert.alert async to avoid bug with Modal After this change, ModalForm will not close until alert opened in onSubmit is dismissed. Related issue: https://github.com/facebook/react-native/issues/... — committed to bappogroup/bappo-open by williamfeng91 6 years ago
- Fixed Modal buttons not responsive when we show an error dialog Alert.alert cancels Modal dismiss even so we end up with a non responsive Modal confirmation dialog. This is explained here: https://gi... — committed to ElyDev/YungDevz by ElyDev 5 years ago
today I met the similar problem after I upgraded the react-native from 0.33 to 0.37. I want to show an Alert dialog after close the Modal, but Modal doesn’t disappear, even after I close the Alert dialog and use
cmd + R
to reload the app. only in iOS, and it works fine by react-native 0.33.the code likes following:
then I try to use
setTimeout
to work around it, the code likes following:then the Modal will disappear, but, the Alert dialog can’t display!!!
I also tried run
setTimeout
insetState
callback, like this:but the same result, Alert dialog doesn’t pop up yet.
finally, I decide to hide Modal after I close the Alert dialog, and that works! code likes following:
+1
Any update/resolution to this? We’re still having problems with this a month after this issue was first reported.
Using
setTimeout
is NOT a safe way to avoid this problem. I recommend usingonDismiss
props in iOS to do something after the modal closed (includingAlert
some messages). I created a class namedModalView
to replace RNModal
class.Using
Just replace your
Modal
withModalView
and addref
props.Show Modal
Close Modal
Alert some messages after the modal closed.
hey, current maintainer of Modal here. The Modal-Alert combination (or really any followup interaction from Modal closing) has been pretty tough to get working right.
I’ll try to spend some time on it this Friday, I think the proper solution would be to add some kind of onClose handler that let’s JS do a follow up action when we can be certain that native has navigated away already.
The best workaround is to wait for the end of the animation and then run Alert in the next “tick” using setTimeout without the second argument. You will be independent of the animation duration:
For everyone who suggest to use timers: Maybe this bullshit codding is ok for JS or Android… but for native iOS developer it looks 100% unacceptable. Better to disable modal animation at all…
@Jlexyc Take it easy. No one is forcing you to use RN. Go with Ionic, or w/e, if you don’t like it or you are not satisfied by the development work being done.
still have it in rn 0.59.8
I think use setTimeout() is the best solution right now.
@yogesh1490
I have a similar problem, but the alert may appear at an undetermined point in time and is not logically dependent on Modal component.
My workaround looks like this:
This is “magic,” but it works for me.
Modal
isn’t really being actively maintained, and is going to be moved out of the React Native core in the future as the “slimmening” commences. I’d recommend migrating off of it in favor of something like React Navigation’s StackNavigator. Example:How is this still an issue after a YEAR? Updating RN 0.47 to 0.48.3 re-introduced this error AGAIN!
Upgrading to RN 0.50.x brings too many breaking changes that make it worth it.
This makes RN so frustrating to work with. Wasting two whole days just to deal with this, to end up creating a
position: absolute
View on top. Christ!SIMPLE WORKAROUND DISCOVERED
Note: setTimeOut does not work for me.
Setup recursive requestAnimationFrame to force the call to be done during seperate frames.
Also, you’re right @susan-github, the presentViewController is done during the wrong time. Also the dismissViewController needs to be called from the parentViewController. For some reason, the ModalView maintains the modal view controller between app states. @ericvicenti there could be something to do with the way the modal is presented then dismissed. At least now we have an easy work around.
In iOS/Swift I have had strange results with having a ModalView be tied to the window, it needs to be tied to the parent view controller.
WORK AROUND
Your guys can try setting the Modal with
animationType="none"
, so the Modal can disappear immediately.Same here. any update on this?
For anyone interested, a simple fix is to wrap with a
setTimeout
.This is still broken in RN v0.40.0
Hi everyone, I solved this problem by adding 100ms timeout as recommended in the comments above. I guess we need to set timeout and waiting for the modal close first
Hi guys. Have the same issue right now. Are there any plans to resolve this in near future?
UPD: Solved this by adding 500ms timeout as in the comments above
After asked iOS developer, it is caused by presentViewController. presentView will be show after the previous one closed completely. While after compare 0.38 with 0.33 version, the Modal component start using presentViewController, which then lead to conflict with Alert.
@baurine Had the same problem with RN 35, a little higher timeout worked for me (600), but ultimately i also did what you did, hide the modal on OK Pressed in Alert
return Alert.alert('Σφάλμα','Η υπηρεσία δεν είναι διαθέσιμη αυτή τη στιγμή. Παρακαλούμε δοκιμάστε σε λίγο.', [ {text: 'OK', onPress: () =>this.setState ({spinnerIsVisible:false})} ])
Still an issue with RN 0.61.2 - does anyone if this is fixed in any later 0.61 patch releases?
Yes, @cristianoccazinsp I think this is the only possible solution as of now because the other availed solution didn’t help me in any way. As from the last 2 days I was stuck in this issue, I started giving a try to the “AlertIOS” component and fortunately found it successful.
Yes, Alerts uses AlertIOS behind it, but don’t know how it got successful? Maybe something lacks in implementing of AlertIOS in Alert behind the scenes.
To be more specific to the code for both platforms;
I’m also having this issue on RN
0.57.8
@DevBkIL my not great solution is to set a timeout, enough for the presented view controller to be the one under the Modal, and then present the Alert. Like I said, not great, but it’s working until this can be properly resolved.
I noticed same issue with experimental navigator. An Error while transitioning kills the animation and freezes UI.
I think facebook engineering need fix this bug.
I’ve build my own modal with
position='absolute'
and it works perfectly without additional delays for Alert. Also you can build custom appearance animation for it. So just don’t use modal out of the box.As @baurine did good investigation.
Until someone come with good solution below hack is work for me. The issue is conflict between Model and Alert. As he said Model need 500ms to dismiss before you show alert.
@slorber Fair enough, but this should be a design decision, not forced because the underlying tech is broken.
Come on, please adress this issue
ionic instead of RN… really? (facepalm)
It’s not a surprise that it is OK for JS, it’s a timeout, it’s Javascript, it’s async bridge. There are a lot of concepts that make this workaround a very natural solution.
On Wed, 1 Mar 2017 at 13:56 Oleksii notifications@github.com wrote:
I can confirm this using https://github.com/jaysoo/react-native-prompt
any workaround?
@ericvicenti I didn’t use NE or Navigator in demo at all, and I don’t think this issue is related to
InteractionManager
, my guess is thatModal
andAlert
are using the same controller or view, so there will be a conflict when trying to control them simultaneously, I know nothing about iOS or I would be glad to make a PR, because it’s really annoying but has a quite common use caseIn my demo, I’ve show the different results when waiting for a certain milliseconds. I guess the
Modal
need 500ms to dismiss, so it’s safe to show theAlert
after 500ms. Perhaps you are right to tieModal
animations intoInteractionManager
, but what if I show theAlert
first as @ganmor mentioned above, I can’t close theAlert
manually, or if I could, would there be the same occasion that we need to wait for theInteractionManager
before showing theModal
?Would someone expert in iOS take a look at this issue?
@cristianoccazinsp The first thing I used was
InteractionManager.runAfterInteractions
, but for some reason, this did not work for me, so I had to make 2requestAnimationFrame
to defer the call toAlert.alert
to the next iteration in the event loop.To add to the above, it really depends on the device you are using. For lower-end devices that run slower, you need a higher timeout. My usual timeout is 300ms.
Given this is such a major issue and such a common use-case I’m still surprised it has persisted for 2 years. Any updates @ericvicenti ?
I just published my first RN package after few weeks of learning/using this framework – and yes its far more better than other cross platform out there.
The package includes a custom ActionSheet that uses the modal which works well for me (disabled the default animation and created my own). If anyone interested: https://github.com/lodev09/react-native-cell-components
I’m not sure if this is the same issue, but if I hide the modal while dismissing the keyboard the modal re-appears and the contents can’t be interacted with.
The opposite is also true, showing an alert in the same loop just before showing a modal will prevent the modal from being displayed
I have same issue here when i use “react-native”: “0.59.9” and “react-native-modal”: “^11.3.1”
And my solution is show the alert in Modal onDismiss props
Hi all, I’ll be closing this because we may fixes it in master branch, feel free to reopen if you think bug not fixed.
In some cases, it is really useful to have the Modal component available. I do not consider the stack navigator with modal transition as a complete replacement for it.
I work with React Navigation Stack Navigator, however, we need some alternative flows for tablets for our custom flow (which is similar to iOS SplitView design to make advantage of tablets size), in those flows, Modal becomes handy when we have to display something in top of the rest of the whole UI.
An example: Left pane: Stack Navigator (1), Right pane: Stack Navigator (2) … In top of it: Modal
For this scenario, if you use Stack Navigator modal transition, you cannot display something in the whole screen. You can however, display that in the left of right pane.
We are having a similar issue in niftylettuce/react-native-loading-spinner-overlay. Could it be that this is a more general issue relating to UI updating on state change rather than just a modal issue?
+1
Looks like we need
<Modal>
animations to tie intoInteractionManager
. A PR would be appreciated for this!Any issues with NavigationExperimental should be filed separately.
2 years later and it is still a thing. Can’t hide 2 modals in a single setState call because of this. You got to manually set a timeout for the second one to close.
Just an FYI - while it’s not ideal and should be fixed, I’ve had the 10ms setTimeout out in production for months now without issue.
@tiendn That’s what we use but it’s a potential race condition if for some reason the initial modal doesn’t dismiss quickly enough
It seems that commit a389ffbd84224b583e71cf7c1468409cbc91ec8e resolves this issue. It looks like it will be shipped with RN 0.50, try it now by upgrading to 0.50 RC 1:
$ react-native-git-upgrade v0.50.0-rc.1
and add this to the modal component:
+1 react-native-cli: 2.0.1 react-native: 0.48.4
ping @ericvicenti
@revich2 interesting… Why do you need 2
requestAnimationFrame
? Would it be the same withrunAfterInteractions
?@react-native-bot can we re open this?
You can use my solution (prevent opening Modal when Alert is opened, and open it after Alert was closed, using redux and hooks).
My solution is not full, later I will send solution that prevents opening many Modals at same time and prevents opening Alert while Modal is closing (based on queue and store subscribe).
In any case, you can refine my idea.
Modal + Alert.zip
Still having this issue. I am showing a loader on screen which is a Modal and then I need to show popup after API response. It works on Android to hide loader on Ok button action of Alert popup, but not working on iOS. Loader gets stuck on screen and popup never appears. Getting this error on Xcode : Warning: Attempt to present <RCTModalHostViewController: 0x7fda01a0d970> on <UIViewController: 0x7fd9fe447fd0> which is already presenting <RCTModalHostViewController: 0x7fda01a0d2d0> Need to kill the app and restart it. Can anyone have solution?
same question! It’s very incredible. I found, the question always appears in the real machine, but not in the simulator.
The timeouts solutions have worked for me. My problem is that when the component is updated, if I was showing an Alert.alert in iOs, the alert disappears right after the setState or Redux update. I think it must have to be with some lifecycle event issue or re-rendering the component, which makes the alert in iOs to go away. I hope this to get solved in the near future. Thank you.
I just tried this out and
onDismiss
seems to work for me.The below code is probably not good practice
The way iOS handles modals, It’s almost the same as doing …
When I tried the above code, iOS only shows the first alert, and Android only shows the 2nd alert.
Possible solution for dismissing modal after an Alert
Assuming you have a modal like
Possible solution for showing an Alert after dismissing a modal
Just in case you have a button or some other action, that triggered the visibility of your modal, and you want to know which button did that when the modal closes, feel free to use
this.setState({modal_triggered_by: 'action1'})
in that action, and then usethis.state.modal_triggered_by
in the modalsonDismiss
But having said all this, I do agree that the behaviour of Modal/Alert combination should work out of the box, and should be identical on both platforms.
@isaachinman totally agree, just giving you this as a hint to solve your problem. As you can see I advocated to keep this issue open
+1 Still a problem on iOS with RN 0.53.3 ( Android Modal works fine RN 0.53.3 )
I really DO NOT like the setTimeout work-around.
@baurine Has the best work-around.
Set the Modal visible isProcessing state to false when the Alert is closed or dismissed.
Instead of using
setTimeout()
,react-native-modal
also has aonModalHide
prop callback that can be used to show the alert after the modal has hidden. This can be a bit less fragile.I’m experiencing the same problem. I have also tried to add the alert in the setState callback but the problem remains:
this.setState({ loadingModalVisible: false, }, () => alert(msg));
hey sorry, I got caught up with some other things at work. I looked into this a bit and it seems like #10303 might actually be able to fix this. Could any of you try it and let me know? If so we can work on getting that merged
UPDATE: UI will be blocked when show Share/ActionSheet while closing Modal too And if we are showing the Alert/Share/ActionSheet, then show a Modal, the UI will be froze too ping @javache @mkonicek