UseRef audio current duration is NaN issue

Viewed 23

I have an <audio/> src with a preload="metadata" tag defined but when I try to get the duration via useRef it is always NaN the first time

import { useGlobalContext } from '../../contexts/context';

const MyComponent = () => {
const {
    audioPlayer,
    playerState,
    setPlayerState,
    ...
} = useGlobalContext();

return (
      <div className={style.Player}>
<audio
          ref={audioPlayer}
          src={`${process.env.REACT_APP_BASE_URL}${playerState.currentItem.url_path}`}
          preload="metadata"
        ></audio>
      </div>
    );
}
// context.js
import React, { useContext, useState, useRef, useEffect } from 'react';
const AppContext = React.createContext();

const AppProvider = ({ children }) => {
// references
  const audioPlayer = useRef(); // reference our audio component

useEffect(() => {
    if (!audioPlayer.current) return; // have to add this to avoid crash during initial page load/render
    // audioPlayer.current is a valid object with a duration value, but duration gives NaN below for no reason
    const seconds = Math.floor(audioPlayer.current.duration);

    setPlayerState((playerState) => ({
      ...playerState,
      duration: seconds,
    }));
    progressBar.current.max = seconds;
    
  }, [
    playerState?.currentItem,
    audioPlayer?.current?.loadedmetadata,
    audioPlayer?.current?.readyState,
  ]);
};

//global hook
const useGlobalContext = () => {
  return useContext(AppContext);
};

export { AppProvider, useGlobalContext };

However, when I comment out the useEffect and reference duration via an onLoadedMetadata callback rather than useRef it gets the duration correctly at the right time.

const MyComponent = () => {
    ...
    const onLoadedMetadata = ()=>{
    const seconds = Math.floor(audioPlayer.current.duration);

    setPlayerState((playerState) => ({
      ...playerState,
      duration: seconds,
    }));
    progressBar.current.max = seconds;
    
   ...
      return (
        ...
        <audio
          ref={audioPlayer}
          src={`${process.env.REACT_APP_BASE_URL}${playerState.currentItem.url_path}`}
          preload="metadata"
          onLoadedMetadata={onLoadedMetadata}
        ></audio>...)
  };

How do I make it work using the useEffect implementation above. Thanks

0 Answers
Related