useEffect与video元素duration异常:对象显示有效值但直接读取为NaN
解决React中useRef获取video元素duration为NaN的问题
问题原因
你遇到的情况是因为视频元数据尚未加载完成时,直接访问duration属性会返回NaN。而console.dir()是惰性求值的——当你在控制台展开元素对象时,视频的元数据已经加载完毕,所以能看到正确的duration值,但同步打印的代码执行瞬间,元数据还没加载好,因此输出NaN。
解决方案
要正确获取视频时长,需要监听视频的loadedmetadata事件,该事件会在视频元数据(包括时长、分辨率等)加载完成后触发。
方案1:在useEffect中绑定事件监听
import { useRef, useState, useEffect } from 'react'; function VideoPlayer() { const videoRef = useRef(null); const [totalTime, setTotalTime] = useState(0); useEffect(() => { const videoElement = videoRef.current; if (!videoElement) return; // 元数据加载完成后获取时长 const handleMetadataLoaded = () => { setTotalTime(videoElement.duration); console.log('正确时长:', videoElement.duration); }; // 绑定事件 videoElement.addEventListener('loadedmetadata', handleMetadataLoaded); // 组件卸载时清理事件监听 return () => { videoElement.removeEventListener('loadedmetadata', handleMetadataLoaded); }; }, []); return ( <video ref={videoRef} src="你的视频地址" controls /> ); }
方案2:直接在video元素上绑定事件属性
import { useRef, useState } from 'react'; function VideoPlayer() { const videoRef = useRef(null); const [totalTime, setTotalTime] = useState(0); return ( <video ref={videoRef} src="你的视频地址" controls onLoadedMetadata={() => { if (videoRef.current) { setTotalTime(videoRef.current.duration); } }} /> ); }
额外说明
如果视频是动态加载的(比如src是后续通过状态更新的),需要在useEffect的依赖数组中加入src状态,确保视频地址变化时重新绑定事件监听。
内容的提问来源于stack exchange,提问作者Mukadas Maltiti
相关产品推荐
相关产品推荐

