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

React中生成Blob URL时web播放器无显示问题求助

React Blob URL 视频刷新后无法加载的问题修复

你的代码存在两个核心问题导致视频重启服务器可显示、刷新后无法加载:

  1. useEffect依赖错误:将videoObjectURL加入依赖数组,状态更新时会重复触发副作用,且清理函数会提前撤销刚生成的Blob URL。
  2. 重复请求与清理时机混乱:每次videoObjectURL变化都会重新执行副作用,清理阶段会错误撤销仍在使用的URL,同时可能重复发起无效的fetch请求。

修改后的代码

import React, { useState, useEffect, useRef } from 'react';

const eBlob = (videoUrl) => {
  const [videoObjectURL, setVideoObjectURL] = useState('');
  const processedUrl = useRef(''); // 跟踪已处理的视频URL,避免重复请求

  useEffect(() => {
    let isMounted = true;
    let currentObjectURL = '';

    const loadVideo = async () => {
      try {
        // 跳过已处理过的URL,避免重复请求
        if (processedUrl.current === videoUrl) return;

        const response = await fetch(videoUrl);
        const videoBlob = await response.blob();
        currentObjectURL = URL.createObjectURL(videoBlob);

        if (isMounted) {
          setVideoObjectURL(currentObjectURL);
          processedUrl.current = videoUrl;
        }
      } catch (error) {
        console.error('加载视频出错:', error);
        processedUrl.current = ''; // 出错后重置,允许后续重试
      }
    };

    loadVideo();

    // 清理当前副作用周期内生成的URL,避免内存泄漏
    return () => {
      isMounted = false;
      if (currentObjectURL) {
        URL.revokeObjectURL(currentObjectURL);
      }
    };
  }, [videoUrl]); // 仅依赖videoUrl,避免循环触发副作用

  return videoObjectURL;
};

export default eBlob;

关键修改说明

  • 移除videoObjectURL的依赖:仅保留videoUrl作为副作用触发条件,彻底避免状态更新导致的循环执行。
  • 用useRef跟踪处理状态:通过processedUrl记录已完成加载的视频URL,防止同一URL重复发起fetch请求。
  • 清理函数使用局部变量:用currentObjectURL保存当前周期生成的Blob URL,确保清理的是当前副作用产生的资源,不会误撤销正在使用的URL。
  • 错误处理重置跟踪状态:视频加载失败时重置processedUrl,允许后续重新尝试加载。

额外注意事项

  • 确保传入的videoUrl是稳定值(比如来自props时用useMemo包裹),避免不必要的重新加载。
  • 若视频资源较大,可添加加载状态提示,提升用户体验。

内容的提问来源于stack exchange,提问作者Ulf FrostyPaw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:17:27