报错:Cannot read properties of null (reading 'play') 原因及解决
解决React中按钮播放音频重叠及报错问题
问题原因分析
- 原代码每次点击按钮都会创建新的
Audio实例,导致多个音频同时播放出现重叠。 - 你尝试的
document.getElementById(sound)之所以报错,是因为sound是导入的音频文件路径(编译后会转为资源URL),并非DOM元素的id,所以找不到对应元素返回null,调用play()自然触发Cannot read properties of null (reading 'play')错误。
解决方案:使用useRef保存音频实例
在React组件中,用useRef来存储音频实例,确保整个组件生命周期内只有一个音频对象,既解决重叠问题,又能实现播放/暂停切换功能。
完整代码示例:
import { useRef } from 'react'; import sound from './Pics/Senorita.mp3'; import BsFillPlayCircleFill from 'react-icons/bs'; function Main() { // 用useRef保存音频实例,跨渲染周期保留引用 const audioRef = useRef(null); // 初始化音频实例(仅第一次渲染时创建) if (!audioRef.current) { audioRef.current = new Audio(sound); } const handleAudioClick = () => { const audio = audioRef.current; if (audio.paused) { // 当前处于暂停状态,开始播放 audio.play(); } else { // 当前正在播放,暂停并可选重置播放进度 audio.pause(); // audio.currentTime = 0; // 取消注释后,点击暂停会回到音频开头 } }; return ( <div style={{ display: "flex", justifyContent: "center", fontSize: '40px'}}> <BsFillPlayCircleFill onClick={handleAudioClick} /> </div> ); } export default Main;
关键说明
useRef的作用:useRef的current属性不会随组件渲染重置,能稳定保存音频实例,避免每次点击创建新对象。- 播放状态判断:通过
audio.paused属性判断当前音频是否处于暂停状态,实现点击切换播放/暂停的逻辑。 - 额外优化(可选):如果需要切换图标(播放→暂停),可以添加状态变量
isPlaying,结合useState实现图标切换,提升交互体验。
内容的提问来源于stack exchange,提问作者Maya
相关产品推荐
相关产品推荐

