Build a Drum Machine store updating but component not updating and keypress not working

Building the Drum machine project! Have abstracted almost all of my data from the state of each individual drum pad React component to the Redux store. I try to trace the data flow with logs and I can see that, when clicking on any of them, the action creator is triggered, the reducer is triggered, and, when I subscribe a console.log statement to the store, that the state in the store is changing as well.

I’m returning a new state with the reducer so the issue is not state immutability. Also, I am using connect and mapStateToProps so theoretically the component is subscribed too.

Here is my Codepen.

A few things I’ve tried so far (unsuccessfully):

  • using connect with App vs. AppWrapper (no change)
  • using store.getState().innerText or props.innerText for the display (I have them both there now)
  • using and not using mapDispatchToProps (not using it now)

I think the issue might be mapStateToProps but I have checked and I think it’s formatted in line with how it is supposed to be. Here it is:

const mapStateToProps = (state, ownProps) => {
  return { innerText: state.innerText,
           innerKey: ownProps.innerKey,
           audio_src: ownProps.audio_src,
           audio_title: ownProps.audio_title
         }
} 

Also I tried to use onKeyPress on each audio element and I’m getting no luck with that. Do I need to have the onKeyPress element on an or because if so, don’t know how this would work! Also, is it logical to have the key logic on each individual audio element versus something global to handle it? The only reason I avoided abstracting that to the store was because it seemed like I then would have to figure out some way to get every audio element reference to the store which seemed unnecessarily complicated.

Thank you so much for your help in advance!

for the first problem you have, getting it to play when you press a key, I would advise adding a keyCode prop to each Pad element and your handleKeyPress would look something like this:

  handleKeyPress(event) {
    if(event.keyCode == this.props.keyCode) {
      this.state.audioRef.current.play();
    }
  }

Just to add onto kravmaguy’s suggestion, I prefer event.key since it’s more readable (i.e. if you console log while pressing the c key it will show “c” instead of a numeric code). Plus, MDN shows keyCode as being deprecated.

For testing try:

handleKeyPress(event) {
    console.log(event.key)
}
1 Like

you can attach event listener for that to document in a component did mount.

For those who are reading this thread later on, I did this from this thread like this:

  componentDidMount() {
    document.addEventListener('keydown', this.handleKeyPress);
  }
  componentWillUnmount() {
    document.removeEventListener('keydown', this.handleKeyPress);
  }

@kravmaguy @SixStringsCoder Thank you so much! That worked!

Any idea for the Redux stuff? No worries if not, I’ll post on StackOverflow!

Thanks again for your help!

EDIT: Nevermind, I also figured this one out!

Basically, before I had it as:

connect(mapStateToProps)(App);
class AppWrapper extends React.Component {
  render() {
    return(
      <Provider store={store}>
        <App />
      </Provider>
    );
  }
}

ReactDOM.render(<AppWrapper />, document.getElementById("app"));

I needed to put the CONNECTED app in the AppWrapper, like this:

const ConnectedApp = connect(mapStateToProps)(App);

class AppWrapper extends React.Component {
  render() {
    return(
      <Provider store={store}>
        <ConnectedApp />
      </Provider>
    );
  }
}

ReactDOM.render(<AppWrapper />, document.getElementById("app"));


Thanks again for your help!

1 Like

and put this in handlekeypress

         store.dispatch(changeText(this.props.audio_title));