Skip to content

Forward RCTEventDispatcher observer events to C++ Native Animated - #59770

Open
zeyap wants to merge 1 commit into
react:mainfrom
zeyap:export-D129152896
Open

zeyap wants to merge 1 commit into
react:mainfrom
zeyap:export-D129152896

Conversation

@zeyap

@zeyap zeyap commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary:
Problem: With C++ Native Animated enabled on iOS, native-driven Animated.event mappings no longer receive events that libraries deliver through RCTEventDispatcher observers. The legacy ObjC Native Animated module observed them; C++ Native Animated only reads Fabric event payloads (event dispatched with eventEmitter->dispatchEvent(name, folly::dynamic)), and codegen'd component events are not readable from C++.

As a result, in some of react-navigation (oss library) examples, Gesture- and pager-driven animations (swipe-back in a JS stack navigator, tab indicators driven by a pager's onPageScroll) stop tracking user input.

Proposed change: When C++ Native Animated is enabled, RCTInstance observes its RCTEventDispatcher and hands each component event, on the main thread, to an EventEmitterListenerContainer it publishes in the context container under RCTEventDispatcherListeners. On Apple platforms, NativeAnimatedNodesManagerProvider::getOrCreate() adds its event listener to that container when present, next to its Fabric event listener.

An alternative is to let the library migrate to EventEmitter::dispatchEvent; however that way the event is also delivered to JS. In android and RNCXX, we also maintain 2 paths to intercept js dispatchEvent and platform-only event.

Changes:

  • iOS (RCTInstance, new RCTEventDispatcherEventPayload): registers as an RCTEventDispatcherObserver only when cxxNativeAnimatedEnabled() is on, and forwards only component events (RCTEventEmitter.receiveEvent). The payload reads values from the event body on demand, so events no listener reads are not converted; it is never dispatched to JS.
  • C++ (NativeAnimatedNodesManagerProvider, __APPLE__ only): subscribes to RCTEventDispatcherListeners from the UIManager's context container. Covers the platform-driven and shared animation backend setups, and apps that create their own provider.
  • C++: EventEmitterListener.h moves from react/renderer/animated to react/renderer/core (the runtime only needs core); react/renderer/animated/EventEmitterListener.h forwards to it for existing includers.

No public API changes.

Found while auditing cxxNativeAnimatedEnabled against OSS react-navigation (7.x) and its peers react-native-gesture-handler, react-native-pager-view and react-native-screens.

Changelog:
[iOS][Fixed] - Native-driven Animated.event mappings receive events delivered through RCTEventDispatcher observers when C++ Native Animated is enabled

Differential Revision: D129152896

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 2, 2026
@facebook-github-tools facebook-github-tools Bot added p: Facebook Partner: Facebook Partner labels Nov 2, 2026
@meta-codesync

meta-codesync Bot commented Nov 2, 2026

Copy link
Copy Markdown

@zeyap has exported this pull request. If you are a Meta employee, you can view the originating Diff in D129152896.

Summary:
**Problem**: With C++ Native Animated enabled on iOS, native-driven `Animated.event` mappings no longer receive events that libraries deliver through `RCTEventDispatcher` observers. The legacy ObjC Native Animated module observed them; C++ Native Animated only reads Fabric event payloads (event dispatched with `eventEmitter->dispatchEvent(name, folly::dynamic)`), and codegen'd component events are not readable from C++.

As a result, in some of `react-navigation` (oss library) examples, Gesture- and pager-driven animations (swipe-back in a JS stack navigator, tab indicators driven by a pager's `onPageScroll`) stop tracking user input.

**Proposed change**: When C++ Native Animated is enabled, `RCTInstance` observes its `RCTEventDispatcher` and hands each component event, on the main thread, to an `EventEmitterListenerContainer` it publishes in the context container under `RCTEventDispatcherListeners`. On Apple platforms, `NativeAnimatedNodesManagerProvider::getOrCreate()` adds its event listener to that container when present, next to its Fabric event listener.

An **alternative** is to let the library migrate to `EventEmitter::dispatchEvent`; however that way the event is also delivered to JS. In android and RNCXX, we also maintain 2 paths to intercept js dispatchEvent and platform-only event.

**Changes**:
- iOS (`RCTInstance`, new `RCTEventDispatcherEventPayload`): registers as an `RCTEventDispatcherObserver` only when `cxxNativeAnimatedEnabled()` is on, and forwards only component events (`RCTEventEmitter.receiveEvent`). The payload reads values from the event body on demand, so events no listener reads are not converted; it is never dispatched to JS.
- C++ (`NativeAnimatedNodesManagerProvider`, `__APPLE__` only): subscribes to `RCTEventDispatcherListeners` from the UIManager's context container. Covers the platform-driven and shared animation backend setups, and apps that create their own provider.
- C++: `EventEmitterListener.h` moves from `react/renderer/animated` to `react/renderer/core` (the runtime only needs `core`); `react/renderer/animated/EventEmitterListener.h` forwards to it for existing includers.

No public API changes.

Found while auditing `cxxNativeAnimatedEnabled` against OSS react-navigation (7.x) and its peers react-native-gesture-handler, react-native-pager-view and react-native-screens.

Changelog:
[iOS][Fixed] - Native-driven `Animated.event` mappings receive events delivered through `RCTEventDispatcher` observers when C++ Native Animated is enabled

Differential Revision: D129152896
@zeyap
zeyap force-pushed the export-D129152896 branch from 7bc5cda to 607205e Compare November 2, 2026 22:55

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant