rive-app / rive-app/rive-react-native
Android bridgeless: all view events fail — getJSModule(RCTEventEmitter) throws on BridgelessReactContext
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 783
- Forks
- 81
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 3
Description
Description
Under bridgeless New Architecture on Android, every event RiveReactNativeView emits throws, because the view emits through the legacy RCTEventEmitter JS module and BridgelessReactContext.getJSModule does not support it.
The practical effect is that onLoop, onStateChanged, onPlay, onStop and onRiveEventReceived never reach JS, with no error surfaced on the JS side — the callback simply never fires. For a looping animation it also produces continuous logcat spam, roughly one stack trace per loop.
Stack trace
E unknown:BridgelessReactContext:
at com.facebook.react.runtime.BridgelessReactContext.getJSModule(BridgelessReactContext.kt:133)
at com.facebook.react.uimanager.ThemedReactContext.getJSModule(ThemedReactContext.kt:74)
at com.rivereactnative.RiveReactNativeView.onLoopEnd(RiveReactNativeView.kt:255)
at com.rivereactnative.RiveReactNativeView$1.notifyLoop(RiveReactNativeView.kt:128)
at app.rive.runtime.kotlin.controllers.RiveFileController.notifyLoop(RiveFileController.kt:1022)
at app.rive.runtime.kotlin.renderers.RiveArtboardRenderer.advance(RiveArtboardRenderer.kt:74)
Cause
RiveReactNativeView.kt dispatches events via reactContext.getJSModule(RCTEventEmitter::class.java). I count nine such call sites in the current release (9.8.5) — lines 222, 233, 244, 255, 265, 304, 493 and 1118, plus the import at line 33:
// android/src/main/java/com/rivereactnative/RiveReactNativeView.kt
33: import com.facebook.react.uimanager.events.RCTEventEmitter
248: fun onLoopEnd(animationName: String, loopMode: RNLoopMode) {
255: reactContext.getJSModule(RCTEventEmitter::class.java)
getJSModule throws unconditionally on a BridgelessReactContext, so every one of these paths is dead when newArchEnabled=true.
The usual migration is UIManagerHelper.getEventDispatcherForReactTag(reactContext, viewTag) with an Event subclass, which works under both the bridge and bridgeless.
Versions
rive-react-native: 9.8.1, and verified unchanged in 9.8.5 (latest at time of writing) by inspecting the published tarballreact-native: 0.81.5- Expo SDK 55
android/gradle.properties:newArchEnabled=true- Reproduced on a release build; a debug build surfaces it differently
Note on #190
#190 is closed and looks related, but it is a different symptom — the "'RiveReactNativeView' is not Fabric compatible yet" banner on RN 0.72 / rive 4.1.2. Rendering works fine here; it is specifically the event dispatch that fails. I could not find an existing issue covering this, but apologies if I have missed one.
Workaround for anyone hitting this
Rendering and autoplay are unaffected, so if you only use Rive decoratively you will see log spam and nothing else. If you depend on a completion callback, drive it from a timer instead and make the handler idempotent, since the native callback may never arrive:
const doneOnce = React.useRef(false);
const handleComplete = React.useCallback(() => {
if (doneOnce.current) return;
doneOnce.current = true;
onComplete();
}, [onComplete]);
// Load-bearing under bridgeless: onStateChanged never fires.
React.useEffect(() => {
const id = setTimeout(handleComplete, ANIMATION_MS);
return () => clearTimeout(id);
}, [handleComplete]);
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in android/src/main/java/com/rivereactnative/RiveReactNativeView.kt at the listed RCTEventEmitter call sites, especially onLoopEnd and the stack-trace entry points. Inspect the bridgeless event-dispatch path and verify the reported release configuration; done means all listed callbacks reach JavaScript under bridgeless and bridge configurations without exceptions or recurring logcat spam.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin, react-native
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100