React音频组件状态问题:如何仅更新单个元素的state
解决React多音频组件状态同步更新问题
你的问题核心在于所有音频共用了同一组全局状态(current、dur、bar),不管操作哪个音频,调用setState都会更新这几个全局变量,导致所有音频的进度信息同步变化。
解决方案:拆分独立子组件
把单个音频的UI和状态封装成独立的AudioItem组件,让每个音频实例自己管理专属状态,这样状态更新只会影响当前音频。
修改后的完整代码如下:
// 单个音频子组件 const AudioItem = ({ song }) => { const [current, setCurrent] = useState("00:00"); const [dur, setDur] = useState("00:00"); const [bar, setBar] = useState("0%"); // 格式化时间为MM:SS格式 const formatTime = (seconds) => { if (isNaN(seconds)) return "00:00"; const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; }; const playPause = () => { const audio = document.getElementById(`audio-${song.id}`); audio.paused ? audio.play() : audio.pause(); }; const timeUpdate = () => { const audio = document.getElementById(`audio-${song.id}`); if (!audio.duration) return; const rawdur = audio.duration; const curTime = audio.currentTime; setCurrent(formatTime(curTime)); setDur(formatTime(rawdur)); // 计算进度条百分比 const progress = (curTime / rawdur) * 100; setBar(progress); }; const skip = (event) => { const audio = document.getElementById(`audio-${song.id}`); const barPosition = event.currentTarget; const clickX = event.clientX - barPosition.getBoundingClientRect().left; const percent = clickX / barPosition.offsetWidth; audio.currentTime = percent * audio.duration; }; return ( <div className="audio-container"> <h3>{song.title}</h3> <h5>{song.artist}</h5> <div className="audio-progress"> <div className="current">{current}</div> <div className="length">{dur}</div> <div className="bar-postion" onClick={skip}> <div className="audio-bar" style={{ width: `${bar}%` }}></div> </div> </div> <audio id={`audio-${song.id}`} src={song.src} onTimeUpdate={timeUpdate} ></audio> {/* 添加播放暂停按钮,方便操作 */} <button onClick={playPause}>播放/暂停</button> </div> ); }; // 父组件 const Audio = () => { const songs = { song: [ { id: 1, src: "http://192.168.1.15:4000/video/audio.mp3", title: "La calin", artist: "Sernath Drums" }, { id: 2, src: "http://192.168.1.15:4000/video/audio2.mp3", title: "Ek Raat", artist: "Dark Music Production" } ] }; return ( <div className='body'> {songs.song.map((song) => ( <AudioItem key={song.id} song={song} /> ))} </div> ); }; export default Audio;
关键改动说明
- 状态私有化:每个
AudioItem拥有自己的current、dur、bar状态,更新时只会影响自身 - 时间格式化:新增
formatTime函数,把原始秒数转为用户友好的MM:SS格式 - 绑定音频事件:给
<audio>标签添加onTimeUpdate事件,自动触发时间更新逻辑,无需手动调用 - 独立DOM选择器:音频ID加上前缀
audio-,避免ID冲突(虽然原ID是唯一的,但更规范)
内容的提问来源于stack exchange,提问作者aman patel
相关产品推荐
相关产品推荐

