diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index 40cfa512e5c..25f9eec7fd8 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -38,8 +38,6 @@ using namespace facebook::react; _imageView.layer.minificationFilter = kCAFilterTrilinear; _imageView.layer.magnificationFilter = kCAFilterTrilinear; - _imageResponseObserverProxy = std::make_shared(self); - self.contentView = _imageView; } @@ -124,6 +122,11 @@ using namespace facebook::react; _state = state; if (_state) { + // A new observer per subscription: callbacks of a previous request can still be queued on the + // main queue (e.g. after this view was recycled and reused), and must not be applied here. + // The callbacks are matched by the proxy's address. The new proxy is allocated before the + // previous one is released, so two consecutive subscriptions never share an address. + _imageResponseObserverProxy = std::make_shared(self); auto &observerCoordinator = _state->getData().getImageRequest().getObserverCoordinator(); observerCoordinator.addObserver(_imageResponseObserverProxy); } @@ -140,8 +143,9 @@ using namespace facebook::react; - (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(const void *)observer { - if (!_eventEmitter || !_state) { - // Notifications are delivered asynchronously and might arrive after the view is already recycled. + if (!_eventEmitter || !_state || observer != _imageResponseObserverProxy.get()) { + // Notifications are delivered asynchronously and might arrive after the view is already recycled, + // or after it has been reused for another image. // In the future, we should incorporate an `EventEmitter` into a separate object owned by `ImageRequest` or `State`. // See for more info: T46311063. return; @@ -187,7 +191,7 @@ using namespace facebook::react; total:(int64_t)total fromObserver:(const void *)observer { - if (!_eventEmitter) { + if (!_eventEmitter || observer != _imageResponseObserverProxy.get()) { return; } @@ -196,6 +200,10 @@ using namespace facebook::react; - (void)didReceiveFailure:(NSError *)error fromObserver:(const void *)observer { + if (observer != _imageResponseObserverProxy.get()) { + return; + } + _imageView.image = nil; if (!_eventEmitter) {