From a304cb43c6a1b9dca196dc57009b9bb2d0ed150d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fo=C5=99t?= Date: Fri, 10 Nov 2023 14:43:11 +0100 Subject: [PATCH] Make the interop-layer work with components with custom name (#41376) * Make the interop-layer work with components with custom name (#41207) Summary: This should fix https://github.com/facebook/react-native/issues/37905#issuecomment-1774851214 When working on react-native-fast-image, we realized that the interop layer does not work for components where the exported name is different from the iOS class. To fix this, we can use the Bridge to retrieve the actual view manager, given the component name. This solution should be much more robust than making assumptions on the ViewManager name, given the ComponentName. On top of that, we realized tha the interop layer was not calling `didSetProps` after setting the props, so we are invoking that. bypass-github-export-checks [iOS][Fixed] - Add support for Components with custom names in the interop layer. Pull Request resolved: https://github.com/facebook/react-native/pull/41207 Test Plan: Tested locally on an app created in 0.72 and 0.73 in Bridge and Bridgeless mode. Reviewed By: cortinico Differential Revision: D50698172 Pulled By: cipolleschi fbshipit-source-id: 49aee905418515b0204febbbe6a67c0114f37029 * Remove references to RCTBridgeProxy --------- Co-authored-by: Riccardo Cipolleschi Co-authored-by: Riccardo Cipolleschi --- ...cyViewManagerInteropComponentDescriptor.mm | 28 +++++++++++++++---- .../RCTLegacyViewManagerInteropCoordinator.mm | 4 +++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm index 745154f5208..e6a29f4fbf6 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm @@ -74,19 +74,35 @@ static Class getViewManagerFromComponentName(const std::string &componentName) return nil; } -static std::shared_ptr const constructCoordinator( - ContextContainer::Shared const &contextContainer, - ComponentDescriptor::Flavor const &flavor) +static Class getViewManagerClass(const std::string &componentName, RCTBridge *bridge) +{ + Class viewManager = getViewManagerFromComponentName(componentName); + if (viewManager != nil) { + return viewManager; + } + + // If all the heuristics fail, let's try to retrieve the view manager from the bridge/bridgeProxy + if (bridge != nil) { + return [[bridge moduleForName:RCTNSStringFromString(componentName)] class]; + } + + return nil; +} + +static const std::shared_ptr constructCoordinator( + const ContextContainer::Shared &contextContainer, + const ComponentDescriptor::Flavor &flavor) { - auto componentName = *std::static_pointer_cast(flavor); - Class viewManagerClass = getViewManagerFromComponentName(componentName); - assert(viewManagerClass); auto optionalBridge = contextContainer->find>("Bridge"); RCTBridge *bridge; if (optionalBridge) { bridge = unwrapManagedObjectWeakly(optionalBridge.value()); } + auto componentName = *std::static_pointer_cast(flavor); + Class viewManagerClass = getViewManagerClass(componentName, bridge); + assert(viewManagerClass); + auto optionalEventDispatcher = contextContainer->find>("RCTEventDispatcher"); RCTEventDispatcher *eventDispatcher; if (optionalEventDispatcher) { diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm index d1b0bfff4fc..73ede6873b4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm @@ -92,6 +92,10 @@ using namespace facebook::react; if (props.isObject()) { NSDictionary *convertedProps = convertFollyDynamicToId(props); [_componentData setProps:convertedProps forView:view]; + + if ([view respondsToSelector:@selector(didSetProps:)]) { + [view performSelector:@selector(didSetProps:) withObject:[convertedProps allKeys]]; + } } }