Search code examples
reactjshls.js

How to use Hls.js with React properly?


I am building a react for a video player using Hls.js. I am using React Refs and calling useEffect to get the video element after it is rendard. The issue is I keep getting an error.

import Hls from "hls.js";
import { useEffect, useRef } from "react";

export default function VideoPlayer({ data, className = '', ...props }) {
  const videoRef = useRef();

  useEffect(()=>{
    const hls = new Hls({
      "debug": true
    });

    if (Hls.isSupported()) {
      hls.log = true;
      hls.loadSource = data.src;
      console.log(videoRef)
      hls.attachMedia(videoRef)
      hls.on(Hls.Events.ERROR, (err) => {
        console.log(err)
      });

    } else {
      console.log('load')
    }
  },[])

  return (
    <video
      ref={videoRef}
      controls
      {...props}
      src={data.src}
      className={className}
    />
  )
}

This is the output I get in the console.

[log] > Debug logs enabled for "Hls instance" in hls.js version 1.4.9-0.canary.9343

VideoPlayer.jsx:16 {current: video}current: nullsrc: "blob:http://192.168.0.205/c68f5827-3d23-4656-9479-c64f7f9b2e51"[[Prototype]]: Object VideoPlayer.jsx:17 [log] > attachMedia react-dom.development.js:22839

Uncaught TypeError: media.addEventListener is not a function at BufferController.onMediaAttaching (buffer-controller.ts:181:13) at EventEmitter2.emit (index.js:203:33) at Hls.emit (hls.ts:288:26) at Hls.trigger (hls.ts:296:19) at Hls.attachMedia (hls.ts:360:10) at VideoPlayer.jsx:17:11 at commitHookEffectListMount (react-dom.development.js:23150:26) at commitPassiveMountOnFiber (react-dom.development.js:24926:13) at commitPassiveMountEffects_complete (react-dom.development.js:24891:9) at commitPassiveMountEffects_begin (react-dom.development.js:24878:7)

Screenshot of Error in Console

Seeing that the Hls.js needs to load after the redering, I used the useEffect but still have an issue.

I have reviewed the other suggestion already and still have the issue.

How to use hls.js with react


Solution

  • I was able to figure out my mistake. I wasn't grabbing the current ref

    import Hls from "hls.js";
    import { useEffect, useRef } from "react";
    
    export default function VideoPlayer({ data, className = '', ...props }) {
      const videoRef = useRef();
    
      useEffect(()=>{
        const hls = new Hls({
          "debug": true
        });
    
        if (Hls.isSupported()) {
          hls.log = true;
          hls.loadSource = data.src;
          hls.attachMedia(videoRef.current)
          hls.on(Hls.Events.ERROR, (err) => {
            console.log(err)
          });
    
        } else {
          console.log('load')
        }
      },[data])
    
      return (
        <video
          ref={videoRef}
          controls
          {...props}
          src={data.src}
          className={className}
        />
      )
    }
    

    I hope this helps anyone else. This was a short post but I was able to figure out after making some coffee...