score:14

Accepted answer

You can use useEffect hook to achieve this and adding an event listener to document:

import React, { useEffect } from "react";

export default ({ name }) => {
  useEffect(() => {
    function handleKeyDown(e) {
      console.log(e.keyCode);
    }

    document.addEventListener('keydown', handleKeyDown);

    // Don't forget to clean up
    return function cleanup() {
      document.removeEventListener('keydown', handleKeyDown);
    }
  }, []);

  return <div>Keydown</div>;
};

Here is an example in action.

Assuming the <div> is focused via tabindex or similar, you'd be able to see see in the keydown handler that e.target would be the <div>. You can also wrap the functionality in another component and in it's keydown handler check if the keydown was executed on that element instead of outside using contains.

Here is another example that uses contains to check if the event target is within the div ref:

import React, { useEffect, useRef } from "react";

function Hello({ onKeyDown }) {
  const ref = useRef();

  useEffect(() => {
    function handleKeyDown(e) {
      // check if keydown was contained in target div
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }

      // Emit event to parent component
      onKeyDown(e);
    }

    document.addEventListener("keydown", handleKeyDown);

    return function cleanup() {
      document.removeEventListener("keydown", handleKeyDown);
    };
  }, []);

  return (
    <div ref={ref} tabIndex="0">
      foo bar baz
    </div>
  );
}

export default Hello;

Hopefully that helps!


Related Query

More Query from same tag