Skip to content

Android: unstable callback references can make useRiveTrigger and onEventReceived miss events #230

@edgarrii

Description

@edgarrii

Summary

On Android, after updating @rive-app/react-native from 0.4.2 to 0.4.5, we found a case where Rive trigger/event listeners can silently stop firing if the callback reference changes across React re-renders.

This does not reproduce on iOS with the same .riv files and the same JS logic.

A practical workaround on our side was to make callbacks stable with useEvent / useRef + useCallback([]).

This looks related to listener/property re-subscription timing and may be adjacent to #156, but the repro here does not depend on autoPlay={false}.

Environment

  • @rive-app/react-native: 0.4.5
  • React Native: 0.84.1
  • Platform: Android only
  • Previous working version: 0.4.2

Repro pattern

We use ViewModel triggers and event listeners from React components that can re-render multiple times while the screen is mounted.

Problematic shape:

const { instance: riveInstance } = useViewModelInstance(riveFile, {
  instanceName: theme.isDarkTheme ? 'dark' : 'light',
  viewModelName: 'Theme',
});

useRiveTrigger('animationFinish', riveInstance, {
  onTrigger: () => {
    onAnimationEnd();
    wasAnimationPlayed.current = true;
  },
});

and similarly:

<RiveAnimation
  onEventReceived={(event) => {
    if (event.name === 'anim_finish') {
      showButton();
    }
  }}
/>

In our app, these components re-render several times while mounted. On Android, after the update to 0.4.5, the listener may stop receiving the expected trigger/event.

Workaround

Making the callback reference stable fixes the issue for us:

const handleAnimationFinish = useEvent(() => {
  onAnimationEnd();
  wasAnimationPlayed.current = true;
});

useRiveTrigger('animationFinish', riveInstance, {
  onTrigger: handleAnimationFinish,
});

Expected behavior

Changing the JS callback reference between renders should not cause Android trigger/event delivery to become unreliable.

Actual behavior

On Android, useRiveTrigger(..., { onTrigger }) and event listeners passed through component props can miss expected events/triggers when callback references change across renders.

Notes

We noticed this after the hook/runtime changes introduced in the newer 0.4.x line. From reading the runtime code, it looks like listener/property lifecycle may now be more sensitive to option identity changes during re-render.

Metadata

Metadata

Assignees

No one assigned

    Labels

    androidbugSomething isn't workingquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions