React音频播放器Props传递URL后无法播放的问题求助
搞定你的React音频播放器问题啦!
我看了你的代码,发现问题出在useAudio钩子的Audio实例管理上。你用useState(new Audio(url))创建音频对象,但这个初始化只会在钩子第一次运行时执行一次——哪怕后面url因为props更新变了,这个Audio实例还是指向最开始的那个地址,自然播不了新音频啦!
下面是修改后的完整解决方案:
首先修改Audio3.js里的useAudio钩子,改用useRef来管理Audio实例,并且监听url变化更新音频源:
import React, { useState, useEffect, useRef } from "react"; const useAudio = (url) => { console.log("in useAudio", url); // 用useRef保存Audio实例,生命周期内保持引用 const audioRef = useRef(new Audio(url)); const [playing, setPlaying] = useState(false); const toggle = () => setPlaying(!playing); // 控制播放/暂停的逻辑 useEffect(() => { const audio = audioRef.current; playing ? audio.play() : audio.pause(); }, [playing]); // 重点:监听url变化,更新音频源 useEffect(() => { const audio = audioRef.current; // 先暂停当前播放,避免新旧音频重叠 audio.pause(); // 更新src并加载新音频 audio.src = url; audio.load(); // 如果之前是播放状态,切换音频后自动继续播放 if (playing) { audio.play(); } }, [url, playing]); // 监听音频结束事件,重置播放状态 useEffect(() => { const audio = audioRef.current; const handleEnded = () => setPlaying(false); audio.addEventListener("ended", handleEnded); // 清理函数要移除同一个监听函数,所以单独抽出来命名 return () => { audio.removeEventListener("ended", handleEnded); }; }, []); return [playing, toggle]; }; const Player = (props) => { console.log("the current page is", props.currPage); const url = `https://github.com/cre8ture/audioFilesForBL/blob/main/${props.currPage}.mp3?raw=true`; console.log("the audio 3 is ", url); const [playing, toggle] = useAudio(url); return ( <div> <button onClick={toggle}>{playing ? "Pause" : "Play"}</button> </div> ); }; export default Player;
然后简化一下App.js里多余的handleChange2函数,没必要多绕一层:
import React, { useState } from "react"; import Header from "./components/header"; import ConceptTabs from "./components/threeButtons"; function App() { const [pageID, setPageID] = useState(0); let handleChange = (id) => { console.log("clicked", id); setPageID(id); }; console.log("pageID", pageID); return ( <> <Header currPage={pageID} /> <br /> <ConceptTabs handleChangeProps={handleChange} /> </> ); } export default App;
改动说明:
- 用
useRef替代useState管理Audio实例:useRef的引用在组件整个生命周期里都不会变,而且修改它的current属性不会触发重渲染,适合保存这种需要持续引用的对象。 - 新增
url依赖的useEffect:当props传递的currPage变化导致url更新时,这个effect会自动更新音频的src,加载新资源,还能保持之前的播放状态(如果之前在播放,新音频会自动开始)。 - 优化事件监听:把结束事件的回调单独命名,确保清理时移除的是同一个函数,避免内存泄漏。
现在你点击ONE/TWO/THREE按钮,播放器会自动切换到对应音频,点击Play能正常播放,结束后按钮也会变回Play啦!
内容的提问来源于stack exchange,提问作者Katie Melosto
相关产品推荐
相关产品推荐

