簡體   English   中英

React:將全局 keydown 事件偵聽器傳遞給映射組件

[英]React: Pass global keydown event listener down to mapped components

我正在構建一個鼓機,我希望允許用戶通過鍵盤輸入與行為的按鈕進行交互。 這些按鈕是通過從包含成為 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM