反应:将全局键关闭事件侦听器向下传递到映射的组件



我正在构建一台鼓机,我希望允许用户通过键盘输入与行为的按钮进行交互。这些按钮是通过从包含 react 应用程序中成为道具的对象数组中映射出道具来渲染的。目前,容器组件中有一个状态属性发生更改,该属性显示按下了哪个键盘键。如何将状态属性(或事件信息)从容器组件向下传递到映射组件的映射组件,以及如何获得正确的按钮来播放?

代码如下:

Container.js

class Container extends React.Component {
constructor(props) {
super(props);
this.handlePowerState = this.handlePowerState.bind(this);
this.state = {
sound: "press a button!",
powered: true,
lastPressedKey: null
};
}
componentDidMount() {
document.addEventListener("keydown", this.handleKeyPress);
}
componentWillUnmount() {
document.removeEventListener("keydown", this.handleKeyPress);
}
handleKeyPress = event => {
console.log(event.key);
this.setState({ lastPressedKey: event.key });
};
/*   keyboardPlaySound = e => {
console.log(e.key);
console.log(this.state.lastKeyPressed);
if (this.props.keyPressed === this.props.keyLetter) {
this.props.isPowered && this.audio.play();
this.audio.currentTime = 0;
}
}; */
logTheSound = clipName => {
this.setState({
sound: clipName
});
//console.log(this.state.sound);
};
handlePowerState() {
this.setState({
powered: !this.state.powered
});
}
componentDidUpdate() {
document.addEventListener("keydown", this.keyboardPlaySound);
}
render() {
const ButtonComponents = SoundData.map(button => (
<SoundButton
//onClick={this.playSound}
key={button.keyLetter}
lastPressedKey={event => this.state.lastPressedKey(event)}
onKeyDown={this.handleKeypress}
isPowered={this.state.powered}
keyLetter={button.keyLetter}
button={button.togglePlay}
clipSrc={button.clipSrc}
clipName={button.clipName}
//clip={this.state.sound}
logSound={this.logTheSound}
tabIndexValue={this.tabIndexValue}
>
{button.clipName} {button.key}
</SoundButton>
));
return (
<div className="machine-container">
<main className="button-container">{ButtonComponents}</main>
<div className="mutation-container">
<PowerSwitch
isPowered={this.state.powered}
onChange={this.handlePowerState}
/>
</div>
</div>
);
}
}
export default Container;

SoundButton.js

class SoundButton extends React.Component {
audio = new Audio(this.props.clipSrc);
//console.log(this.mappedSoundObjects);
playSound = event => {
this.props.isPowered && this.audio.play();
this.audio.currentTime = 0;
//console.log(this.props.clipName);
};
keyboardPlaySound = e => {
//console.log(e.key);
console.log(this.props.onKeyDown);
this.props.isPowered && this.audio.play();
this.audio.currentTime = 0;
};
render() {
return (
<button
//style={buttonBottoms}
isPowered={this.props.isPowered}
onClick={event => {
this.playSound();
this.props.logSound(this.props.clipName);
}}
//onKeyDown={this.handleKeyPress}
onKeyDown={event => {
this.keyboardPlaySound();
this.props.logSound(this.props.clipName);
}}
tabIndex={this.tabIndexValue}
//className="clip myButton ui button"
className="buttons"
>
{this.props.keyLetter}
</button>
);
}
}
export default SoundButton;

如代码所示,我正在使用此处所示的挂载/卸载模式,并且我已经尝试了无数种方法,尝试将事件处理程序有条件地路由到正确的按钮。我在所有这些尝试中得到的最好的结果是,在使用键盘上的所有键首次单击按钮后播放声音(任何键盘键都会播放最初单击的相同声音)。同样,如何将容器组件中的事件处理程序路由到正确的映射按钮组件?

也许您应该考虑组件之间的某种通知。 看看这个:它显示了发送可以订阅的消息的组件的实现。 https://jasonwatmore.com/post/2019/02/13/react-rxjs-communicating-between-components-with-observable-subject

最新更新