I'm trying to add an event listener for keydown event in an image (or div) tag. It works if I add it to the document with document.addEventListener, but it doesn't when I try to put it into the specific element that I create in react (I noted in the code what works and what doesn't). Also handleClick works and handleKey does not, no matter which format I put it into the tag with.
class PrescriptionImage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      patient: "",
      rotation: 0
    };
    this.handleKey = this.handleKey.bind(this);
  }
  handleClick() {
    this.setState({rotation: this.state.rotation + 270})
  }
  handleKey(e) {
    e.preventDefault();
    console.log(e);
    if (e.code == 'ArrowLeft') {
      if (e.ctrlKey) {
        this.setState({rotation: this.state.rotation + 270})
      }
    }
  }
  componentDidMount() {
//    document.getElementById("left").addEventListener("keydown", this.handleKey, true); This doesn't work (no error)
//    this.RxImage.addEventListener("keydown", this.handleKey, false); This doesn't work, (can't find addEventListener of "undefined")
//    document.addEventListener("keydown", this.handleKey, false); This works.
    fetch("http://localhost:3333/patientAddress.json")
      .then(res => res.json())
      .then(
        result => {
          this.setState({
            isLoaded: true,
            patient: result.order.patient
          });
        },
        error => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      );
  }
  componentWillUnmount(){
    document.removeEventListener("keydown", this.handleKey, false);
  }
  render() {
    const { error, isLoaded, patient, rotation } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return <img className="prescription-image" style={{width: "98%", height: "98%", transform: `rotate(${rotation}deg)`}} src={"data:image/png;base64," + patient.rx.imageData} onClick={() => this.handleClick()} onKeyDown={this.handleKey} />;
    }
  }
}
ReactDOM.render(<PrescriptionImage />, document.getElementById("left"));
                You got 2 main issues here:
keyDown event needs the div to be in focus. one way to do it
is to add a tabindex attribute to the div. after you focus on it
you can trigger the onKeyDown event on any key on the keyboard.e.code but in fact the
correct property is e.keycode.key for example).EDIT
I have added another approach, using the ref API of react.
This way you can attach an event listener the way you did before and also trigger a focus via code (see componentDidMount).
Here is a running example:
class App extends React.Component {
  componentDidMount() {
    this.myDiv.addEventListener('keydown', this.handleKey);
    this.myDiv.focus();
  }
  componentWillUnmount() {
    this.myDiv.removeEventListener('keydown', this.handleKey);
  }
  handleKey = e => {
    console.log(e.keyCode);
  }
  render() {
    return (
      <div>
        <div tabIndex="0" onKeyDown={this.handleKey}>click me</div>
        <div tabIndex="1" ref={ref => this.myDiv = ref}>by ref</div>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
This implementation worked well for me.
class App extends React.Component {
  constructor(props) {
    super(props);
    this.myDiv = React.createRef();
  }
  componentDidMount() {
    this.myDiv.current.addEventListener('keydown', this.handleKey);
    this.myDiv.current.focus();
  }
  componentWillUnmount() {
    this.myDiv.current.removeEventListener('keydown', this.handleKey);
  }
  handleKey = e => {
    console.log(e.keyCode);
  }
  render() {
    return (
      <div>
        <div tabIndex="0" onKeyDown={this.handleKey}>click me</div>
        <div tabIndex="1" ref={this.myDiv}>by ref</div>
      </div>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With