更新changeStartTime后WaveSurferPlayer组件无法播放问题
问题解决:React中WaveSurferPlayer未响应changeStartTime更新触发播放
核心问题
你的WaveSurferPlayer组件中,处理播放定位的useEffect仅监听了wavesurfer实例,当父组件传递的changeStartTime属性更新时,该effect不会触发,导致seekTo和play逻辑无法执行。此外,原代码还存在重复订阅事件的风险,且未处理音频未加载完成时getDuration()返回0的异常情况。
修复方案
拆分逻辑为两个独立的useEffect:一个处理WaveSurfer事件订阅(仅初始化时执行),另一个专门监听changeStartTime变化并触发定位播放,同时增加音频加载状态检查。
修改后的WaveSurferPlayer.jsx代码:
export const WaveSurferPlayer = (props) => { const containerRef = useRef(); const [playState, setPlayState] = useState(false); const [currentTime, setCurrentTime] = useState(0); const wavesurfer = useWavesurfer(containerRef, props); // 仅在wavesurfer初始化时订阅事件,避免重复订阅 useEffect(() => { if (!wavesurfer) return; const playHandler = () => setPlayState(true); const pauseHandler = () => setPlayState(false); const timeUpdateHandler = (time) => setCurrentTime(time); wavesurfer.on("play", playHandler); wavesurfer.on("pause", pauseHandler); wavesurfer.on("timeupdate", timeUpdateHandler); return () => { wavesurfer.off("play", playHandler); wavesurfer.off("pause", pauseHandler); wavesurfer.off("timeupdate", timeUpdateHandler); }; }, [wavesurfer]); // 监听changeStartTime变化,触发定位播放 useEffect(() => { if (!wavesurfer || props.changeStartTime == null) return; // 确保音频加载完成后再执行定位,避免getDuration返回0 const executeSeekAndPlay = () => { const duration = wavesurfer.getDuration(); if (duration > 0) { wavesurfer.seekTo(props.changeStartTime / duration); wavesurfer.play(); setPlayState(true); } else { // 音频未加载完成时延迟重试 setTimeout(executeSeekAndPlay, 100); } }; executeSeekAndPlay(); }, [wavesurfer, props.changeStartTime]); return ( <> <div ref={containerRef} style={{ minHeight: "120px" }} /> {/* ... 其他代码 */} </> ); };
关键优化点
- 依赖数组加入
props.changeStartTime,确保属性更新时触发播放逻辑 - 拆分事件订阅逻辑,避免每次
changeStartTime变化都重复订阅/取消订阅,减少性能开销和内存泄漏风险 - 增加音频加载检查,解决因音频未加载完成导致
seekTo计算异常的问题 - 明确
changeStartTime的有效性判断,避免空值或无效值触发错误逻辑
内容的提问来源于stack exchange,提问作者유성원
相关产品推荐
相关产品推荐

