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 <riccardo.cipolleschi@gmail.com>
Co-authored-by: Riccardo Cipolleschi <cipolleschi@meta.com>
This commit is contained in:
Marek Fořt
2023-11-10 14:43:11 +01:00
committed by GitHub
co-authored by Riccardo Cipolleschi Riccardo Cipolleschi
parent 5858fd768e
commit a304cb43c6
2 changed files with 26 additions and 6 deletions
@@ -74,19 +74,35 @@ static Class getViewManagerFromComponentName(const std::string &componentName)
return nil;
}
static std::shared_ptr<void> 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<void> constructCoordinator(
const ContextContainer::Shared &contextContainer,
const ComponentDescriptor::Flavor &flavor)
{
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
Class viewManagerClass = getViewManagerFromComponentName(componentName);
assert(viewManagerClass);
auto optionalBridge = contextContainer->find<std::shared_ptr<void>>("Bridge");
RCTBridge *bridge;
if (optionalBridge) {
bridge = unwrapManagedObjectWeakly(optionalBridge.value());
}
auto componentName = *std::static_pointer_cast<std::string const>(flavor);
Class viewManagerClass = getViewManagerClass(componentName, bridge);
assert(viewManagerClass);
auto optionalEventDispatcher = contextContainer->find<std::shared_ptr<void>>("RCTEventDispatcher");
RCTEventDispatcher *eventDispatcher;
if (optionalEventDispatcher) {
@@ -92,6 +92,10 @@ using namespace facebook::react;
if (props.isObject()) {
NSDictionary<NSString *, id> *convertedProps = convertFollyDynamicToId(props);
[_componentData setProps:convertedProps forView:view];
if ([view respondsToSelector:@selector(didSetProps:)]) {
[view performSelector:@selector(didSetProps:) withObject:[convertedProps allKeys]];
}
}
}