You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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)

问题原因

  1. 受控输入警告:range输入的onChange事件仅提供event参数,错误使用第二个参数v会导致v为undefined,调用setVolume(v)后volume状态变为undefined,输入框从受控状态转为非受控状态,触发警告。
  2. TypeError错误:当volume为undefined时,volume/100计算结果为NaN(非有限值),而HTMLMediaElement的volume属性仅接受0-1之间的有效数字,因此抛出错误。
  3. 额外问题:受控组件同时设置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:55:12