如何解决React音频应用中“The provided double value is non-finite”错误?
音乐Web应用音量调节功能的React代码问题修复
问题描述
开发音乐Web应用时添加音量调节功能,触发输入框onChange事件时出现两个问题:
- 控制台提示受控输入变为非受控的警告
- 抛出
TypeError错误:Failed to set the 'volume' property on 'HTMLMediaElement': The provided double value is non-finite
原代码
const audioPlayer = React.useRef(); React.useEffect(()=>{ if(audioPlayer){ audioPlayer.current.volume = volume/100; } },[volume]) <input className="progress-bar progress-bar-2 hidden md:block" type="range" defaultValue={0} min={0} max={100} value={volume} onChange={(e,v) => setVolume(v)} />
错误信息
react-dom.development.js:86 Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components at input at div at div at AudioPlayer (http://localhost:5173/src/components/audioPlayer.jsx:34:7) at div at div at App (http://localhost:5173/src/App.jsx:28:47) printWarning @ react-dom.development.js:86 react-dom.development.js:22839 Uncaught TypeError: Failed to set the 'volume' property on 'HTMLMediaElement': The provided double value is non-finite. at audioPlayer.jsx:103:27 at commitHookEffectListMount (react-dom.development.js:23150:26) at commitPassiveMountOnFiber (react-dom.development.js:24926:13) at commitPassiveMountEffects_complete (react-dom.development.js:24891:9) at commitPassiveMountEffects_begin (react-dom.development.js:24878:7) at commitPassiveMountEffects (react-dom.development.js:24866:3) at flushPassiveEffectsImpl (react-dom.development.js:27039:3) at flushPassiveEffects (react-dom.development.js:26984:14) at commitRootImpl (react-dom.development.js:26935:5) at commitRoot (react-dom.development.js:26682:5)
问题原因
- 受控输入警告:range输入的
onChange事件仅提供event参数,错误使用第二个参数v会导致v为undefined,调用setVolume(v)后volume状态变为undefined,输入框从受控状态转为非受控状态,触发警告。 - TypeError错误:当
volume为undefined时,volume/100计算结果为NaN(非有限值),而HTMLMediaElement的volume属性仅接受0-1之间的有效数字,因此抛出错误。 - 额外问题:受控组件同时设置
defaultValue会导致状态不一致;useEffect未判断audioPlayer.current是否存在,也未校验volume的有效性。
修复步骤及代码
1. 初始化音量状态
确保volume有初始值(示例设为50,对应50%音量):
const [volume, setVolume] = React.useState(50);
2. 修正onChange事件取值
从event.target.value获取输入值并转为数字:
onChange={(e) => setVolume(Number(e.target.value))}
3. 完善useEffect逻辑
增加实例存在性和数值有效性判断,同时限制音量范围:
React.useEffect(()=>{ if(audioPlayer.current && typeof volume === 'number' && !isNaN(volume)){ const clampedVolume = Math.max(0, Math.min(100, volume)); audioPlayer.current.volume = clampedVolume / 100; } },[volume])
4. 移除defaultValue
受控组件仅需绑定value属性:
<input className="progress-bar progress-bar-2 hidden md:block" type="range" min={0} max={100} value={volume} onChange={(e) => setVolume(Number(e.target.value))} />
完整修复后代码
import React from 'react'; const AudioPlayer = () => { const audioPlayer = React.useRef(); const [volume, setVolume] = React.useState(50); React.useEffect(()=>{ if(audioPlayer.current && typeof volume === 'number' && !isNaN(volume)){ const clampedVolume = Math.max(0, Math.min(100, volume)); audioPlayer.current.volume = clampedVolume / 100; } },[volume]) return ( <div> <audio ref={audioPlayer} src="your-audio-source.mp3"></audio> <input className="progress-bar progress-bar-2 hidden md:block" type="range" min={0} max={100} value={volume} onChange={(e) => setVolume(Number(e.target.value))} /> </div> ); }; export default AudioPlayer;
内容的提问来源于stack exchange,提问作者Tomiwa
相关产品推荐
相关产品推荐

