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

React鼓机项目中音量滑块无响应问题求助

问题描述

我正在完成Free Code Camp的鼓机挑战项目,目标是实现点击按钮播放音效的功能。目前尝试添加音量滑块来控制音效音量,但滑块完全没有作用。我在父组件中初始化了volume状态并添加了onChange事件处理函数,将volume作为props传递给包含playSound播放函数的子组件,请问需要修改哪些地方才能让滑块正常工作?

// 音效列表
const ziki = [
  {
    keyCode: 81,
    keyTrigger: "Q",
    id: "Heater-1",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3"
  },
  {
    keyCode: 87,
    keyTrigger: "W",
    id: "Heater-2",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3"
  },
  {
    keyCode: 69,
    keyTrigger: "E",
    id: "Heater-3",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-3.mp3"
  },
  {
    keyCode: 65,
    keyTrigger: "A",
    id: "Heater-4",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3"
  },
  {
    keyCode: 83,
    keyTrigger: "S",
    id: "Clap",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3"
  },
 {
    keyCode: 68,
    keyTrigger: "D",
    id: "Open-HH",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3"
  },
  {
    keyCode: 90,
    keyTrigger: "Z",
    id: "Kick-n'-Hat",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3"
  },
  {
    keyCode: 88,
    keyTrigger: "X",
    id: "Kick",
    url: "https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3"
  },
  {
    keyCode: 67,
    keyTrigger: "C",
    id: "Closed-HH",
    url: "https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3"
  }
];

// 父组件,包含volume状态
class Drum extends React.Component {
  constructor(props) {
    super(props);
    this.state = { volume: 1 };
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(e) {
    this.setState({ volume: e.target.value });
  }
  render() {
    return (
      <div>
        <div>
          <h1 className="text-center">Drum Machine</h1>
          {ziki.map((clip) => (
            <ActualPad key={clip.id} sound={clip} volume={this.state.volume} />
          ))}
        </div>
        <br />
        <p className="text-center">
          <input
            onChange={this.handleChange}
            type="range"
            step="0.01"
            value={this.state.volume}
            min="0"
            max="1"
          />{" "}
        </p>
      </div>
    );
  }
}

// 子组件,接收volume作为props
const ActualPad = (props) => {
  const [active, setActive] = React.useState(false);

  const playSound = () => {
    setActive(true);
    setTimeout(() => setActive(false), 500);
    const audioTag = document.getElementById(props.sound.keyTrigger);
    audioTag.currentTime = 0;
    audioTag.volume = props.volume;
    audioTag.play();
  };

  return (
    <div
      onClick={playSound}
      className={`btn btn-secondary p-4 m-3 ${active && "btn-warning"}`}
    >
      <audio id={props.sound.keyTrigger} src={props.sound.url} />
      {props.sound.keyTrigger}
    </div>
  );
};

ReactDOM.render(<Drum />, document.getElementById("root"));

修改方案

  1. 修复值类型不匹配问题
    range输入框返回的e.target.value是字符串类型,但audio元素的volume属性要求0-1的数值类型。修改父组件的handleChange方法,将输入值转为数字:
handleChange(e) {
  this.setState({ volume: Number(e.target.value) });
}
  1. 实时更新音量(可选优化)
    当前只有点击播放时才设置音量,若想拖动滑块时实时更新所有音效的音量,在子组件中添加useEffect监听音量变化:
React.useEffect(() => {
  const audioTag = document.getElementById(props.sound.keyTrigger);
  if (audioTag) {
    audioTag.volume = props.volume;
  }
}, [props.volume, props.sound.keyTrigger]);
  1. 补全子组件代码
    你提供的子组件代码存在缺失,需要补充函数组件定义和active状态初始化,否则组件无法正常运行(如上面修正后的代码所示)。

内容的提问来源于stack exchange,提问作者Musinga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 07:50:28