Skip to content

Bug: onEnd fires multiple times after re-render on iOS #4896

@AnasAlamin

Description

@AnasAlamin

🐛 Bug: onEnd fires multiple times after re-render on iOS

Description

The onEnd callback is triggered more than once for the same video on iOS when the component re-renders. This leads to unintended side effects such as multiple "play next" actions being fired.


Environment

  • Platform: iOS
  • Library: react-native-video
  • Version: ^6.19.1
  • React Native version: 0.83.4
  • Device: real device

Expected Behavior

onEnd should fire exactly once when the video playback reaches the end.


Actual Behavior

onEnd fires multiple times:

  • once when the video ends
  • again after a re-render (e.g. state update, focus change, or parent re-render)

Reproduction

  1. Render a <Video /> component
  2. Let the video play until completion
  3. Trigger a re-render (e.g. via state change or switching focus)
  4. Observe that onEnd fires again

Minimal Example

const handleEnd = () => {
  console.log("onEnd triggered");
};

<Video
  source={{ uri: videoUrl }}
  onEnd={handleEnd}
/>

Notes / Observations

  • It may be related to the player staying at the end position and re-triggering onEnd on re-render

  • Happens more frequently when:

    • switching focus between videos
    • updating parent state
    • re-mounting or re-binding props

Workarounds Tried

  • Guarding with ref:
if (endedVideoIdsRef.current.has(videoId)) return;
  • Checking active video before handling:
if (videoId !== focusedQueuedVideoId) return;
  • Manually seeking to 0 on focus:
videoRef.current?.seek(0);

These mitigate the issue but do not address the root cause.


Additional Context

This behavior makes it difficult to reliably implement queue-based playback (e.g. auto-playing next video), since onEnd cannot be treated as a single-fire event.


Possible Cause (Speculation)

The player may re-emit onEnd when:

  • the component re-renders while the playback position is at the end
  • the native player re-attaches or updates state

Request

  • Confirm whether this is expected behavior
  • Provide a way to ensure onEnd fires only once per playback cycle
  • Or expose a more reliable "playback completed" signal

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    To Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions