Skip to content

Commit 61bd291

Browse files
cipolleschifortmarek
authored andcommitted
Make the interop-layer work with components with custom name (#41207)
Summary: This should fix #37905 (comment) 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: #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
1 parent 5858fd7 commit 61bd291

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,35 @@ static Class getViewManagerFromComponentName(const std::string &componentName)
7474
return nil;
7575
}
7676

77-
static std::shared_ptr<void> const constructCoordinator(
78-
ContextContainer::Shared const &contextContainer,
79-
ComponentDescriptor::Flavor const &flavor)
77+
static Class getViewManagerClass(const std::string &componentName, RCTBridge *bridge, RCTBridgeProxy *bridgeProxy)
78+
{
79+
Class viewManager = getViewManagerFromComponentName(componentName);
80+
if (viewManager != nil) {
81+
return viewManager;
82+
}
83+
84+
// If all the heuristics fail, let's try to retrieve the view manager from the bridge/bridgeProxy
85+
if (bridge != nil) {
86+
return [[bridge moduleForName:RCTNSStringFromString(componentName)] class];
87+
}
88+
89+
return nil;
90+
}
91+
92+
static const std::shared_ptr<void> constructCoordinator(
93+
const ContextContainer::Shared &contextContainer,
94+
const ComponentDescriptor::Flavor &flavor)
8095
{
81-
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
82-
Class viewManagerClass = getViewManagerFromComponentName(componentName);
83-
assert(viewManagerClass);
8496
auto optionalBridge = contextContainer->find<std::shared_ptr<void>>("Bridge");
8597
RCTBridge *bridge;
8698
if (optionalBridge) {
8799
bridge = unwrapManagedObjectWeakly(optionalBridge.value());
88100
}
89101

102+
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
103+
Class viewManagerClass = getViewManagerClass(componentName, bridge, bridgeProxy);
104+
assert(viewManagerClass);
105+
90106
auto optionalEventDispatcher = contextContainer->find<std::shared_ptr<void>>("RCTEventDispatcher");
91107
RCTEventDispatcher *eventDispatcher;
92108
if (optionalEventDispatcher) {

packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ - (void)setProps:(folly::dynamic const &)props forView:(UIView *)view
9292
if (props.isObject()) {
9393
NSDictionary<NSString *, id> *convertedProps = convertFollyDynamicToId(props);
9494
[_componentData setProps:convertedProps forView:view];
95+
96+
if ([view respondsToSelector:@selector(didSetProps:)]) {
97+
[view performSelector:@selector(didSetProps:) withObject:[convertedProps allKeys]];
98+
}
9599
}
96100
}
97101

0 commit comments

Comments
 (0)