Skip to content

Commit 27a3248

Browse files
grabboualloy
authored andcommitted
[iOS] [Fixed] - Revert [previous incomplete fix](bd2b7d6) for [an issue](#26473) with Modal’s onDismiss prop.
This reverts commit bd2b7d6.
1 parent 8ba46aa commit 27a3248

File tree

5 files changed

+100
-5
lines changed

5 files changed

+100
-5
lines changed

Libraries/Modal/Modal.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212

1313
const AppContainer = require('../ReactNative/AppContainer');
1414
const I18nManager = require('../ReactNative/I18nManager');
15-
const PropTypes = require('prop-types');
15+
const NativeEventEmitter = require('../EventEmitter/NativeEventEmitter');
16+
import NativeModalManager from './NativeModalManager';
17+
const Platform = require('../Utilities/Platform');
1618
const React = require('react');
19+
const PropTypes = require('prop-types');
1720
const ScrollView = require('../Components/ScrollView/ScrollView');
1821
const StyleSheet = require('../StyleSheet/StyleSheet');
1922
const View = require('../Components/View/View');
@@ -22,6 +25,12 @@ import type {ViewProps} from '../Components/View/ViewPropTypes';
2225
import type {DirectEventHandler} from '../Types/CodegenTypes';
2326
import type EmitterSubscription from '../vendor/emitter/EmitterSubscription';
2427
import RCTModalHostView from './RCTModalHostViewNativeComponent';
28+
29+
const ModalEventEmitter =
30+
Platform.OS === 'ios' && NativeModalManager != null
31+
? new NativeEventEmitter(NativeModalManager)
32+
: null;
33+
2534
/**
2635
* The Modal component is a simple way to present content above an enclosing view.
2736
*
@@ -178,9 +187,22 @@ class Modal extends React.Component<Props> {
178187
};
179188
}
180189

190+
componentDidMount() {
191+
if (ModalEventEmitter) {
192+
this._eventSubscription = ModalEventEmitter.addListener(
193+
'modalDismissed',
194+
event => {
195+
if (event.modalID === this._identifier && this.props.onDismiss) {
196+
this.props.onDismiss();
197+
}
198+
},
199+
);
200+
}
201+
}
202+
181203
componentWillUnmount() {
182-
if (this.props.onDismiss != null) {
183-
this.props.onDismiss();
204+
if (this._eventSubscription) {
205+
this._eventSubscription.remove();
184206
}
185207
}
186208

Libraries/Modal/RCTModalHostViewNativeComponent.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ type NativeProps = $ReadOnly<{|
8686
*/
8787
onShow?: ?DirectEventHandler<null>,
8888

89+
/**
90+
* The `onDismiss` prop allows passing a function that will be called once
91+
* the modal has been dismissed.
92+
*
93+
* See https://facebook.github.io/react-native/docs/modal.html#ondismiss
94+
*/
95+
onDismiss?: ?BubblingEventHandler<null>,
96+
8997
/**
9098
* Deprecated. Use the `animationType` prop instead.
9199
*/

React/Views/RCTModalHostViewManager.m

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#import "RCTBridge.h"
1111
#import "RCTModalHostView.h"
1212
#import "RCTModalHostViewController.h"
13+
#import "RCTModalManager.h"
1314
#import "RCTShadowView.h"
1415
#import "RCTUtils.h"
1516

@@ -80,10 +81,15 @@ - (void)presentModalHostView:(RCTModalHostView *)modalHostView withViewControlle
8081

8182
- (void)dismissModalHostView:(RCTModalHostView *)modalHostView withViewController:(RCTModalHostViewController *)viewController animated:(BOOL)animated
8283
{
84+
dispatch_block_t completionBlock = ^{
85+
if (modalHostView.identifier) {
86+
[[self.bridge moduleForClass:[RCTModalManager class]] modalDismissed:modalHostView.identifier];
87+
}
88+
};
8389
if (_dismissalBlock) {
84-
_dismissalBlock([modalHostView reactViewController], viewController, animated, nil);
90+
_dismissalBlock([modalHostView reactViewController], viewController, animated, completionBlock);
8591
} else {
86-
[viewController.presentingViewController dismissViewControllerAnimated:animated completion:nil];
92+
[viewController.presentingViewController dismissViewControllerAnimated:animated completion:completionBlock];
8793
}
8894
}
8995

React/Views/RCTModalManager.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <UIKit/UIKit.h>
9+
10+
#import <React/RCTBridgeModule.h>
11+
#import <React/RCTEventEmitter.h>
12+
13+
@interface RCTModalManager : RCTEventEmitter <RCTBridgeModule>
14+
15+
- (void)modalDismissed:(NSNumber *)modalID;
16+
17+
@end

React/Views/RCTModalManager.m

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import "RCTModalManager.h"
9+
10+
@interface RCTModalManager ()
11+
12+
@property BOOL shouldEmit;
13+
14+
@end
15+
16+
@implementation RCTModalManager
17+
18+
RCT_EXPORT_MODULE();
19+
20+
- (NSArray<NSString *> *)supportedEvents
21+
{
22+
return @[ @"modalDismissed" ];
23+
}
24+
25+
- (void)startObserving
26+
{
27+
_shouldEmit = YES;
28+
}
29+
30+
- (void)stopObserving
31+
{
32+
_shouldEmit = NO;
33+
}
34+
35+
- (void)modalDismissed:(NSNumber *)modalID
36+
{
37+
if (_shouldEmit) {
38+
[self sendEventWithName:@"modalDismissed" body:@{ @"modalID": modalID }];
39+
}
40+
}
41+
42+
@end

0 commit comments

Comments
 (0)