Skip to content

Commit 68ae8cd

Browse files
cipolleschifacebook-github-bot
authored andcommittedJan 31, 2024··
Fix crash in the interop layer when components emits events as soon as are created (#42743)
Summary: Pull Request resolved: #42743 When working on Mobile Home, we found a component (RNCSafeAreaView) that was going through the interop layer. The component eits an event as soon as its content view changes, but this is too early: the block that emits the event is still nil at that point in time and that makes the app crash. There might be other components with similarbehavior, therefore, we are fixing it at the interop layer, setting the props immediately after the component is created. ## Changelog: [iOS][Fixed] - Immediately set props of Components that goes through the interop layer Reviewed By: sammy-SC Differential Revision: D53230471 fbshipit-source-id: 90a19e0e87fea381b348b5a7e723ab8b416b828c
1 parent ae42e02 commit 68ae8cd

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed
 

‎packages/react-native/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm

+22-1
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,20 @@ - (void)updateState:(const State::Shared &)state oldState:(const State::Shared &
210210
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
211211
{
212212
[super finalizeUpdates:updateMask];
213+
__block BOOL propsUpdated = NO;
214+
215+
__weak __typeof(self) weakSelf = self;
216+
void (^updatePropsIfNeeded)(RNComponentViewUpdateMask) = ^void(RNComponentViewUpdateMask mask) {
217+
__typeof(self) strongSelf = weakSelf;
218+
if (!propsUpdated) {
219+
[strongSelf _setPropsWithUpdateMask:mask];
220+
propsUpdated = YES;
221+
}
222+
};
213223

214224
if (!_adapter) {
215225
_adapter = [[RCTLegacyViewManagerInteropCoordinatorAdapter alloc] initWithCoordinator:[self _coordinator]
216226
reactTag:self.tag];
217-
__weak __typeof(self) weakSelf = self;
218227
_adapter.eventInterceptor = ^(std::string eventName, folly::dynamic event) {
219228
if (weakSelf) {
220229
__typeof(self) strongSelf = weakSelf;
@@ -223,6 +232,13 @@ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
223232
eventEmitter.dispatchEvent(eventName, event);
224233
}
225234
};
235+
// Set props immediately. This is required to set the initial state of the view.
236+
// In the case where some events are fired in relationship of a change in the frame
237+
// or layout of the view, they will fire as soon as the contentView is set and if the
238+
// event block is nil, the app will crash.
239+
updatePropsIfNeeded(updateMask);
240+
propsUpdated = YES;
241+
226242
self.contentView = _adapter.paperView;
227243
}
228244

@@ -247,6 +263,11 @@ - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
247263

248264
[_adapter.paperView didUpdateReactSubviews];
249265

266+
updatePropsIfNeeded(updateMask);
267+
}
268+
269+
- (void)_setPropsWithUpdateMask:(RNComponentViewUpdateMask)updateMask
270+
{
250271
if (updateMask & RNComponentViewUpdateMaskProps) {
251272
const auto &newProps = static_cast<const LegacyViewManagerInteropViewProps &>(*_props);
252273
[_adapter setProps:newProps.otherProps];

0 commit comments

Comments
 (0)
Please sign in to comment.