// React integration example. The key detail is lifecycle: createPlayer fully tears // down hls.js + EME on destroy(), so the effect MUST destroy on unmount — and guard // against React 18 StrictMode's double-invoke and rapid prop changes (the #1 // managed-player integration bug). import { useEffect, useRef } from 'react'; import { createPlayer, type Player } from '@oddin-gg/havik-player'; interface Props { baseUrl: string; matchUrn: string; apiKey: string; } export function HavikPlayer({ baseUrl, matchUrn, apiKey }: Props) { const videoRef = useRef(null); useEffect(() => { const video = videoRef.current; if (!video) return; let player: Player | null = null; let cancelled = false; createPlayer({ video, baseUrl, matchUrn, credential: { apiKey }, autoplay: true, muted: true, waitForLive: true, }) .then((p) => { // If the effect was already cleaned up (StrictMode / fast nav), discard. if (cancelled) p.destroy(); else player = p; }) .catch((err) => console.error('havik-player', err)); return () => { cancelled = true; player?.destroy(); }; }, [baseUrl, matchUrn, apiKey]); return