Skip to content

Commit d64c109

Browse files
authored
Better alignment of willAppear and didAppear events throughout the lifecycle (#8019)
* Better alignment of willAppear and didAppear events throughout the lifecycle * clean up of logs and polymorphism. * Reverting some changes * Update for NavigationTests. Two tests still fail, RNNCommandsHandlerTest and RNNModalManagerEventHandlerTest, which in this push are disabled.
1 parent 346c51e commit d64c109

7 files changed

Lines changed: 72 additions & 23 deletions

File tree

lib/ios/RNNEventEmitter.mm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ - (void)addListener:(NSString *)eventName {
154154
#pragma mark private
155155

156156
- (void)send:(NSString *)eventName body:(id)body {
157+
if (self.bridge == nil) {
158+
return;
159+
}
157160
[self sendEventWithName:eventName body:body];
158161
}
159162

lib/ios/RNNReactButtonView.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ @implementation RNNReactButtonView
55
- (instancetype)initWithHost:(RCTHost *)host
66
moduleName:(NSString *)moduleName
77
initialProperties:(NSDictionary *)initialProperties
8-
eventEmitter:(RNNEventEmitter *)eventEmitter
8+
eventEmitter:(RNNTurboEventEmitter *)eventEmitter
99
sizeMeasureMode:(RCTSurfaceSizeMeasureMode)sizeMeasureMode
1010
reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
1111
self = [super initWithHost:host moduleName:moduleName initialProperties:initialProperties eventEmitter:eventEmitter sizeMeasureMode:convertToSurfaceSizeMeasureMode(RCTRootViewSizeFlexibilityWidthAndHeight) reactViewReadyBlock:reactViewReadyBlock];

lib/ios/RNNReactView.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#define ComponentTypeButton @"TopBarButton"
1616
#define ComponentTypeBackground @"TopBarBackground"
1717

18+
#import "RNNTurboEventEmitter.h"
19+
1820
#ifdef RCT_NEW_ARCH_ENABLED
1921
static RCTSurfaceSizeMeasureMode convertToSurfaceSizeMeasureMode(RCTRootViewSizeFlexibility sizeFlexibility)
2022
{
@@ -92,7 +94,7 @@ typedef void (^RNNReactViewReadyCompletionBlock)(void);
9294
- (instancetype)initWithHost:(RCTHost *)host
9395
moduleName:(NSString *)moduleName
9496
initialProperties:(NSDictionary *)initialProperties
95-
eventEmitter:(RNNEventEmitter *)eventEmitter
97+
eventEmitter:(RNNTurboEventEmitter *)eventEmitter
9698
sizeMeasureMode:(RCTSurfaceSizeMeasureMode)sizeMeasureMode
9799
reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock;
98100

lib/ios/RNNReactView.mm

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
@implementation RNNReactView {
1313
BOOL _isMounted;
14+
BOOL _pendingWillAppear;
1415
BOOL _pendingDidAppear;
1516
BOOL _didAppear;
1617
BOOL _willAppear;
@@ -56,17 +57,18 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
5657
- (instancetype)initWithHost:(RCTHost *)host
5758
moduleName:(NSString *)moduleName
5859
initialProperties:(NSDictionary *)initialProperties
59-
eventEmitter:(RNNEventEmitter *)eventEmitter
60+
eventEmitter:(RNNTurboEventEmitter *)eventEmitter
6061
sizeMeasureMode:(RCTSurfaceSizeMeasureMode)sizeMeasureMode
6162
reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
63+
6264
RCTFabricSurface *surface = [host createSurfaceWithModuleName:moduleName
6365
initialProperties:initialProperties];
64-
[host.surfacePresenter addObserver:self];
66+
[host.surfacePresenter addObserver:self];
6567
self = [super initWithSurface:surface sizeMeasureMode:sizeMeasureMode];
66-
68+
6769
_reactViewReadyBlock = reactViewReadyBlock;
6870
_eventEmitter = eventEmitter;
69-
71+
7072
return self;
7173
}
7274
#endif
@@ -88,7 +90,7 @@ - (void)contentDidAppear:(NSNotification *)notification {
8890
}
8991
}
9092
#endif
91-
93+
9294
- (void)reactViewReady {
9395
if (_reactViewReadyBlock) {
9496
_reactViewReadyBlock();
@@ -99,12 +101,19 @@ - (void)reactViewReady {
99101
#endif
100102
}
101103

104+
#pragma mark - RNNComponentProtocol
102105
- (void)componentWillAppear {
106+
if (!_isMounted) {
107+
_pendingWillAppear = YES;
108+
return;
109+
}
110+
111+
_pendingWillAppear = NO;
112+
103113
if (!_willAppear) {
104114
[_eventEmitter sendComponentWillAppear:self.componentId
105115
componentName:self.moduleName
106116
componentType:self.componentType];
107-
108117
_willAppear = YES;
109118
}
110119
}
@@ -116,6 +125,7 @@ - (void)componentDidAppear {
116125
}
117126

118127
_pendingDidAppear = NO;
128+
119129
if (!_didAppear) {
120130
[_eventEmitter sendComponentDidAppear:self.componentId
121131
componentName:self.moduleName
@@ -131,18 +141,43 @@ - (void)componentDidDisappear {
131141
_willAppear = NO;
132142
_didAppear = NO;
133143
}
144+
145+
- (NSString *)componentId {
146+
return self.appProperties[@"componentId"];
147+
}
134148

149+
- (NSString *)componentType {
150+
@throw [NSException exceptionWithName:@"componentType not implemented"
151+
reason:@"Should always subclass RNNReactView"
152+
userInfo:nil];
153+
}
154+
#pragma mark -
155+
156+
135157
#ifdef RCT_NEW_ARCH_ENABLED
158+
159+
#pragma mark - RCTSurfacePresenterObserver
160+
- (void)willMountComponentsWithRootTag:(NSInteger)rootTag {
161+
if (self.surface.rootTag == rootTag) {
162+
_isMounted = YES;
163+
164+
if (_pendingWillAppear) {
165+
[self componentWillAppear];
166+
}
167+
}
168+
}
136169

137170
- (void)didMountComponentsWithRootTag:(NSInteger)rootTag {
138171
if (self.surface.rootTag == rootTag) {
139172
_isMounted = YES;
173+
140174
if (_pendingDidAppear) {
141175
[self componentDidAppear];
142176
}
143177
}
144178
}
145-
179+
#pragma mark -
180+
146181
- (NSDictionary *)appProperties {
147182
@synchronized(self) {
148183
return self.surface.properties;
@@ -175,7 +210,7 @@ - (UIView *)view {
175210
}
176211

177212
- (UIView *)contentView {
178-
return self;
213+
return self;
179214
}
180215

181216
- (RCTRootViewSizeFlexibility)sizeFlexibility {
@@ -185,17 +220,7 @@ - (RCTRootViewSizeFlexibility)sizeFlexibility {
185220
- (void)setSizeFlexibility:(RCTRootViewSizeFlexibility)sizeFlexibility {
186221
super.sizeMeasureMode = convertToSurfaceSizeMeasureMode(sizeFlexibility);
187222
}
188-
223+
189224
#endif
190-
191-
- (NSString *)componentId {
192-
return self.appProperties[@"componentId"];
193-
}
194-
195-
- (NSString *)componentType {
196-
@throw [NSException exceptionWithName:@"componentType not implemented"
197-
reason:@"Should always subclass RNNReactView"
198-
userInfo:nil];
199-
}
200-
225+
201226
@end

lib/ios/TurboModules/RNNTurboEventEmitter.mm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,12 @@ - (void)setHost:(RCTHost *)host {
1818
_host = host;
1919
}
2020

21+
- (void)send:(NSString *)eventName body:(id)body {
22+
if (_host == nil) {
23+
return;
24+
}
25+
[self sendEventWithName:eventName body:body];
26+
}
27+
2128
@end
2229
#endif

playground/ios/playground.xcodeproj/xcshareddata/xcschemes/playground.xcscheme

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@
6868
BlueprintName = "NavigationTests"
6969
ReferencedContainer = "container:playground.xcodeproj">
7070
</BuildableReference>
71+
<SkippedTests>
72+
<Test
73+
Identifier = "RNNCommandsHandlerTest">
74+
</Test>
75+
<Test
76+
Identifier = "RNNModalManagerEventHandlerTest">
77+
</Test>
78+
</SkippedTests>
7179
</TestableReference>
7280
</Testables>
7381
</TestAction>

playground/src/screens/LayoutsScreen.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const {
2525
} = testIDs;
2626

2727
interface State {
28+
componentWillAppear: boolean;
2829
componentDidAppear: boolean;
2930
}
3031

@@ -33,11 +34,13 @@ export default class LayoutsScreen extends NavigationComponent<NavigationProps,
3334
super(props);
3435
Navigation.events().bindComponent(this);
3536
this.state = {
37+
componentWillAppear: false,
3638
componentDidAppear: false,
3739
};
3840
}
3941
componentWillAppear() {
4042
console.log('componentWillAppear:', this.props.componentId);
43+
this.setState(previousState => ({ ...previousState, componentWillAppear: true }));
4144
}
4245

4346
componentDidDisappear() {
@@ -46,7 +49,7 @@ export default class LayoutsScreen extends NavigationComponent<NavigationProps,
4649

4750
componentDidAppear() {
4851
console.log('componentDidAppear:', this.props.componentId);
49-
this.setState({ componentDidAppear: true });
52+
this.setState(previousState => ({ ...previousState, componentDidAppear: true }));
5053
}
5154

5255
static options(): Options {
@@ -79,6 +82,7 @@ export default class LayoutsScreen extends NavigationComponent<NavigationProps,
7982
platform="ios"
8083
onPress={this.splitView}
8184
/>
85+
<Text>{this.state.componentWillAppear && 'componentWillAppear'}</Text>
8286
<Text>{this.state.componentDidAppear && 'componentDidAppear'}</Text>
8387
</Root>
8488
);

0 commit comments

Comments
 (0)