Skip to content

Unable to dispatch a custom event from Fabric components #34072

@justblender

Description

@justblender

Description

I've set up a custom Codegen component with a property of onProgress, which infers DirectEventHandler<Readonly<...>> type.

Codegen correctly identifies its type and generates an event emitter for this component, but dispatching it from Objective-C++ results in always receiving an Unsupported top level event type topXYZ is dispatched error.

Simulator Screen Shot - iPhone 13 - 2022-06-25 at 20 45 43

Version

0.69.0

Output of npx react-native info

System:
    OS: macOS 12.4
    CPU: (8) arm64 Apple M1
    Memory: 270.31 MB / 8.00 GB
    Shell: 3.3.1 - /opt/homebrew/bin/fish
  Binaries:
    Node: 17.8.0 - /opt/homebrew/bin/node
    Yarn: 3.2.0 - /opt/homebrew/bin/yarn
    npm: 8.5.5 - /opt/homebrew/bin/npm
    Watchman: Not Found
  Managers:
    CocoaPods: 1.11.3 - /opt/homebrew/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
    Android SDK: Not Found
  IDEs:
    Android Studio: 2021.2 AI-212.5712.43.2112.8609683
    Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.15 - /opt/homebrew/Cellar/openjdk@11/11.0.14.1/libexec/openjdk.jdk/Contents/Home/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 18.0.0 => 18.0.0
    react-native: 0.69.0 => 0.69.0
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Steps to reproduce

  1. Declare native Codegen component with any onEventName event handler prop.
  2. On the native side, acquire an instance of the generated EventEmitter class and dispatch any generated event.

Snack, code example, screenshot, or link to a repository

  1. Declare codegen native component TestComponent with onProgress event handler prop.
// @ts-ignore TODO: remove once there is a .d.ts file with definitions
import codegenNativeComponentUntyped from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps, HostComponent } from 'react-native';
import type {
  Int32,
  WithDefault,
  DirectEventHandler,
  // @ts-ignore TODO: remove once there is a .d.ts file with definitions
} from 'react-native/Libraries/Types/CodegenTypes';

interface NativeProps extends ViewProps {
  onProgress?: DirectEventHandler<
    Readonly<{
      bytesWritten: Int32;
      bytesExpected: Int32;
    }>
  >;
}

const codegenNativeComponent = codegenNativeComponentUntyped as <T extends {}>(
  name: string
) => HostComponent<T>;

export default codegenNativeComponent<NativeProps>('TestComponent');
  1. On the native side, acquire an instance of the generated TestComponentEventEmitter class:
  - (std::shared_ptr<const TestComponentEventEmitter>)getEventEmitter
{
  if (!self->_eventEmitter) {
    return nullptr;
  }

  assert(std::dynamic_pointer_cast<TestComponentEventEmitter const>(self->_eventEmitter));
  return std::static_pointer_cast<TestComponentEventEmitter const>(self->_eventEmitter);
}
  1. Dispatch onProgress event:
const auto eventEmitter = [self getEventEmitter];
if (eventEmitter) {
  eventEmitter->onProgress(TestComponentEventEmitter::OnProgress{
    .bytesWritten = bytesWritten,
    .bytesExpected = bytesExpected
  });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: New ArchitectureIssues and PRs related to new architecture (Fabric/Turbo Modules)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions