You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 16:28:14