React中生成Blob URL时web播放器无显示问题求助
React Blob URL 视频刷新后无法加载的问题修复
你的代码存在两个核心问题导致视频重启服务器可显示、刷新后无法加载:
- useEffect依赖错误:将
videoObjectURL加入依赖数组,状态更新时会重复触发副作用,且清理函数会提前撤销刚生成的Blob URL。 - 重复请求与清理时机混乱:每次
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
相关产品推荐
相关产品推荐

