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