React 实现本地音频上传播放功能 修复Audio播放后无法暂停问题
问题根因
你代码无法暂停的核心原因是:Audio实例被你放在了组件渲染逻辑中,每次组件触发重渲染(比如调用setButtonName修改按钮文本状态时),都会重新执行整个组件函数,只要audio状态有值,就会创建一个全新的Audio实例,你调用pause操作的是这个从未播放过的新实例,自然不会生效。
修复后完整代码
import React, { useState, useRef, useEffect } from 'react'; const AudioPlay = () => { const [buttonName, setButtonName] = useState('Play'); // 用useRef存储Audio实例,保证全局唯一,不会随渲染重置 const audioRef = useRef(null); // 存储objectURL用于后续清理 const audioUrlRef = useRef(null); const handleClick = () => { if (!audioRef.current) return; if (buttonName === 'Play') { audioRef.current.play(); setButtonName('Pause'); } else { audioRef.current.pause(); setButtonName('Play'); } }; const addFile = (e) => { const file = e.target.files[0]; if (!file) return; // 先清理之前的音频资源 if (audioRef.current) { audioRef.current.pause(); URL.revokeObjectURL(audioUrlRef.current); } const audioUrl = URL.createObjectURL(file); audioUrlRef.current = audioUrl; // 仅在上传文件时创建一次Audio实例 audioRef.current = new Audio(audioUrl); setButtonName('Play'); }; // 组件卸载时清理资源,避免内存泄漏 useEffect(() => { return () => { if (audioRef.current) { audioRef.current.pause(); } if (audioUrlRef.current) { URL.revokeObjectURL(audioUrlRef.current); } }; }, []); return ( <div> <button onClick={handleClick} disabled={!audioRef.current}>{buttonName}</button> <input type='file' accept="audio/*" onChange={addFile} /> </div> ); }; export default AudioPlay;
主要改动说明
- 用useRef存储Audio实例和生成的临时资源链接,保证实例不会随组件重渲染被重新创建,播放和暂停操作的始终是同一个音频对象
- 仅在上传新音频文件时创建Audio实例,避免重复实例化
- 新增了资源清理逻辑,切换音频、组件卸载时都会释放之前创建的临时URL,避免内存泄漏
- 给按钮增加了禁用态、给文件选择框增加了
audio/*的类型限制,优化使用体验
内容的提问来源于stack exchange,提问作者Ganesh Lamichhane
相关产品推荐
相关产品推荐

