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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions