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

