Using onKeyDown on a certain element will require focus to work as intended.

We can make your MdOutlinePause component focus-able by adding the tabindex attribute. That will allow you to give the icon focus by hitting tab or by clicking on it. The element would look something like this:

<MdOutlinePause tabIndex={0} onKeyDown={handleKey} />

If you want to detect the key event without having to focus the element, you will need to attach an event listener. We can do this with useEffect so this happens onMount, and we'll attach the event listener to the window so it works regardless of which element has focus:

  /// Don't copy and paste this - see below
  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);
    });
  }, []);
  /// Don't copy and paste this - see below

This allows you to detect the keyboard event, which is great, but there's an issue: the eventListener gets added again whenever the page mounts, but is never removed. So you will likely run into issues of your function getting called multiple times on each keyPress.

We can fix this by removing the event listener in the return from useEffect. This is how we specify a function to let the useEffect clean up after itself. This ensures that our useEffect is never adding more than one "keydown" event listener at a time:

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, []);

Here's a full example on codesandbox

This works great if you don't need to access state in your handleKeyPress function.


It is a common use case to need to do something with state variables when the user does a certain action, and if we need to access updated state then we run into a problem: we attached handleKeyPress to the event listener onMount and the function never gets updated, so it will always use the initial version of state. This codesandbox illustrates the issue.

We can fix this by adding handleKeyPress to the dependencies array for useEffect, but this results in our event listener being removed and re-added on every render since handleKeyPress will be updated on each render. A better solution is to use the callback pattern with our handleKeyPress so that it is only updated when actually necessary (when the state it depends on is updated). We also want to add handleKeyPress to our useEffect dependency array so we create a new event listener when the handleKeyPress function changes:

  const handleKeyPress = useCallback((event) => {
    // do stuff with stateVariable and event
  }, [stateVariable]);

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, [handleKeyPress]);

Now everything updates appropriately! Here's a full example of this on codesandbox.


There's one more solution which lets you access state in the simplest way possible. The downside is that the only state variable you have access to (with updated values) will be the state variable you are updating, so this solution is situational. To access other state variables, you'll have to use the solution above.

By passing a function to useState, we can access the previous state as the first argument of the function. This allows for a much simpler approach, shown below and in this codesandbox.

  const [text, setText] = useState("");

  const handleKeyPress = event => {
    setText(previousText => `${previousText}${event.key}`);
  };

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, []);

Answer from Andrew Hulterstrom on Stack Overflow
Top answer
1 of 1
9

Using onKeyDown on a certain element will require focus to work as intended.

We can make your MdOutlinePause component focus-able by adding the tabindex attribute. That will allow you to give the icon focus by hitting tab or by clicking on it. The element would look something like this:

<MdOutlinePause tabIndex={0} onKeyDown={handleKey} />

If you want to detect the key event without having to focus the element, you will need to attach an event listener. We can do this with useEffect so this happens onMount, and we'll attach the event listener to the window so it works regardless of which element has focus:

  /// Don't copy and paste this - see below
  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);
    });
  }, []);
  /// Don't copy and paste this - see below

This allows you to detect the keyboard event, which is great, but there's an issue: the eventListener gets added again whenever the page mounts, but is never removed. So you will likely run into issues of your function getting called multiple times on each keyPress.

We can fix this by removing the event listener in the return from useEffect. This is how we specify a function to let the useEffect clean up after itself. This ensures that our useEffect is never adding more than one "keydown" event listener at a time:

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, []);

Here's a full example on codesandbox

This works great if you don't need to access state in your handleKeyPress function.


It is a common use case to need to do something with state variables when the user does a certain action, and if we need to access updated state then we run into a problem: we attached handleKeyPress to the event listener onMount and the function never gets updated, so it will always use the initial version of state. This codesandbox illustrates the issue.

We can fix this by adding handleKeyPress to the dependencies array for useEffect, but this results in our event listener being removed and re-added on every render since handleKeyPress will be updated on each render. A better solution is to use the callback pattern with our handleKeyPress so that it is only updated when actually necessary (when the state it depends on is updated). We also want to add handleKeyPress to our useEffect dependency array so we create a new event listener when the handleKeyPress function changes:

  const handleKeyPress = useCallback((event) => {
    // do stuff with stateVariable and event
  }, [stateVariable]);

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, [handleKeyPress]);

Now everything updates appropriately! Here's a full example of this on codesandbox.


There's one more solution which lets you access state in the simplest way possible. The downside is that the only state variable you have access to (with updated values) will be the state variable you are updating, so this solution is situational. To access other state variables, you'll have to use the solution above.

By passing a function to useState, we can access the previous state as the first argument of the function. This allows for a much simpler approach, shown below and in this codesandbox.

  const [text, setText] = useState("");

  const handleKeyPress = event => {
    setText(previousText => `${previousText}${event.key}`);
  };

  useEffect(() => {
    window.addEventListener("keydown", handleKeyPress);

    return () => {
      window.removeEventListener("keydown", handleKeyPress);
    };
  }, []);

🌐
Felix Gerschau
felixgerschau.com › react-typescript-onkeyup-event-type
TypeScript definition for onKeyUp React event
import React, { KeyboardEvent } from 'react'; const App = () => { const handleKeyboardEvent = (e: KeyboardEvent<HTMLImageElement>) => { // Do something }; return <div onKeyUp={handleKeyboardEvent}>{/** Some code */}</div>; }; export default App; onKeyDown · onKeyDownCapture ·
Discussions

Firing a button onKeyUp?
I'm fairly certain the onKeyUp event will only work within an input or similar control. You could create the handleKeyUp method as a prop on the button component and then call it from outside of the component if there is an input elsewhere. More on reddit.com
🌐 r/reactjs
4
1
July 27, 2018
How to detect which React component triggers onKeyUp event?
How do I make it so the handler can detect if the onKeyUp was triggered from login or pwd? More on stackoverflow.com
🌐 stackoverflow.com
May 22, 2017
Add `onKeyUp` and` onKeyDown` support?
Solution 1) That TextInputs (and perhaps other components, but for now at least that one) allow web-specific custom onKeyDown and/or onKeyUp handlers and ensure that onKeyPress is as close to the React Native behavior as possible (as it currently is, i think). More on github.com
🌐 github.com
3
February 1, 2018
reactjs - handling `onKeyUp` for a div - Stack Overflow
I want to handle a key clicked on the keyboard to run a function, I'm trying to do: but there is no benef... More on stackoverflow.com
🌐 stackoverflow.com
🌐
GeeksforGeeks
geeksforgeeks.org › reactjs › react-onkeyup-event
React onKeyUp Event - GeeksforGeeks
July 23, 2025 - React onKeyUp is an event listener that is used to detect the key release event in a browser using JavaScript.
🌐
DevExtreme
js.devexpress.com › React › Documentation › 21_1 › Guide › UI_Components › TextBox › Handle_the_Keyboard_Events
React TextBox - Handle the Keyboard Events | React Documentation v21.1
<template> <DxTextBox @key-down="onKeyDown" @key-press="onKeyPress" @key-up="onKeyUp" @enter-key="onEnterKey" /> </template> <script> import 'devextreme/dist/css/dx.light.css'; import { DxTextBox } from 'devextreme-vue/text-box'; export default { components: { DxTextBox }, methods: { onKeyDown(e) { const keyCode = e.event.key; // Event handling commands go here }, onKeyPress(e) { const keyCode = e.event.key; // Event handling commands go here }, onKeyUp(e) { const keyCode = e.event.key; // Event handling commands go here }, onEnterKey(e) { // Event handling commands go here } } } </script> imp
🌐
Pluralsight
pluralsight.com › tech insights & how-to guides › tech guides & tutorials
How to Use the Enter Key Event Handler on a React-Bootstrap Input Component | Pluralsight
April 16, 2025 - The event onKeyUp checks the event char code being triggered by the end user, and if it is 13, then the event has been generated by the enter key. Otherwise, the state value is not updated into the component state object.
🌐
W3Schools
w3schools.com › jsref › event_onkeyup.asp
onkeyup Event
The onkeyup event occurs when the user releases a key on the keyboard.
🌐
Reddit
reddit.com › r/reactjs › firing a button onkeyup?
r/reactjs on Reddit: Firing a button onKeyUp?
July 27, 2018 -

Currently have a button that I want to fire using the Enter key in a class component but for some reason it's not working. Any ideas?

  handleKeyUp(event) {
    if (event.keyCode === 13) {
      console.log('Enter key has been pressed')
    }
  }

  render() {
    return(
      <div>
        <button
          onKeyUp={ this.handleKeyUp }
        >
          Submit
        </button>
      </div>
    );
  }
Find elsewhere
🌐
StackBlitz
stackblitz.com › edit › react-input-keyup
React Input Keyup - StackBlitz
Starter project for React apps that exports to the create-react-app CLI.
🌐
DevExtreme
js.devexpress.com › React › Documentation › Guide › UI_Components › TextArea › Handle_the_Keyboard_Events
React TextArea - Handle the Keyboard Events | React Documentation
<template> <DxTextArea @key-down="onKeyDown" @key-up="onKeyUp" @enter-key="onEnterKey" /> </template> <script> import 'devextreme/dist/css/dx.light.css'; import { DxTextArea } from 'devextreme-vue/text-area'; export default { components: { DxTextArea }, methods: { onKeyDown(e) { const keyCode = e.event.key; // Event handling commands go here }, onKeyUp(e) { const keyCode = e.event.key; // Event handling commands go here }, onEnterKey(e) { // Event handling commands go here } } } </script> import React from 'react'; import 'devextreme/dist/css/dx.light.css'; import { TextArea } from 'devextreme
🌐
React
react.dev › reference › react-dom › components › common
Common components (e.g. <div>) – React
export default function KeyboardExample() { return ( <label> First name: <input name="firstName" onKeyDown={e => console.log('onKeyDown:', e.key, e.code)} onKeyUp={e => console.log('onKeyUp:', e.key, e.code)} /> </label> ); }
🌐
GitHub
github.com › necolas › react-native-web › issues › 791
Add `onKeyUp` and` onKeyDown` support? · Issue #791 · necolas/react-native-web
February 1, 2018 - Solution 1) That TextInputs (and perhaps other components, but for now at least that one) allow web-specific custom onKeyDown and/or onKeyUp handlers and ensure that onKeyPress is as close to the React Native behavior as possible (as it currently is, i think).
Author   alexandergunnarson
🌐
npm
npmjs.com › package › react-native-keyevent
react-native-keyevent - npm
December 11, 2023 - Override the default keyboard event behavior // super.onKeyUp(keyCode, event); // return true; // 2. Keep default keyboard event behavior // return super.onKeyUp(keyCode, event); // Using method #1 super.onKeyUp(keyCode, event); return true; } @Override public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { KeyEventModule.getInstance().onKeyMultipleEvent(keyCode, repeatCount, event); return super.onKeyMultiple(keyCode, repeatCount, event); } ...... } This will need to be added in your AppDelegate.m file: // react-native-keyevent #import <RNKeyEvent.h> // import our packag
      » npm install react-native-keyevent
    
Published   Dec 11, 2023
Version   0.3.2
Author   Kevin Johnson
🌐
KindaCode
kindacode.com › article › react-typescript-handling-keyboard-events
React + TypeScript: Handling Keyboard Events - KindaCode
June 8, 2022 - // App.tsx // Kindacode.com import React, { useState } from "react"; import "./App.css"; const App = () => { const [enteredText, setEnteredText] = useState(""); // onKeyDown handler function const keyDownHandler = (event: React.KeyboardEvent<HTMLInputElement>) => { if (event.code === "Enter") { alert(`You have typed "${enteredText}"`); } }; // onKeyUp handler function const keyUpHandler = (event: React.KeyboardEvent<HTMLInputElement>) => { if (event.code === "Escape") { const confirm = window.confirm( "Are you sure want to clear this text feild?"
🌐
Medium
medium.com › @stheodorejohn › exploring-keyboard-and-focus-events-in-react-d6c05d1e4926
Exploring Keyboard and Focus Events in React | by Theodore John.S | Medium
June 28, 2023 - Lets unleash the power of interactivity in React with keydown, keyup, keypress, focus, and blur events. Elevate user experiences and create…
Top answer
1 of 2
8

You have to capture the keypress then in body/window level. Table element doesn't have input focus so you can't capture the keys from table (without input element).

var cmdDown = false;

document.body.addEventListener('keydown', function(event) {
  var key = event.keyCode || event.charCode || 0;
  if ([91,93,224,17].indexOf(key) !== -1) {
    cmdDown = true;
  }
  console.log('CMD DOWN: ' + cmdDown.toString());    
});

document.body.addEventListener('keyup', function(event) {
  var key = event.keyCode || event.charCode || 0;
  if ([91,93,224,17].indexOf(key) !== -1) {
    cmdDown = false;
  }
  console.log('CMD DOWN: ' + cmdDown.toString());
});

2 of 2
3

Simple Example

I believe best practice here is to add an event listener to document and modify your element (e.x. table) accordingly. Extending u/Hardy's answer with a full React component:

class MyComponent extends React.Component {

  // Using an arrow function. Alternatively, could bind() this 
  // function in the component's constructor
  keydownHandler = (event) => {
    // Add logic, e.x. check event.keyCode to see 
    // if CMD is pressed and then update state
  }

  componentDidMount() {
    document.addEventListener("keydown", this.keydownHandler);
  }

  componentWillUnmount() {
    this.removeEventListener("keydown", this.keydownHandler);
  }

  render() {
    <div>Hello World</div>
  }
}

Alternative

As others have noted, there are challenges in using keyboard events that are bound to non-input elements, as browsers require those elements to be in focus in order to invoke the bound callbacks. Another approach that seems to work is to set the tabindex property of the component to bring the element in focus. From u/burak's answer:

render() {
  <div onKeyDown={this.keydownHandler} tabindex={-1}>Example</div>
}

This has the benefit of connecting into React's Synthetic Events, that is "a cross-browser wrapper around the browser’s native event." However, when modifying the tabindex property it's important to be mindful that this could change the order of focusable elements, and affect a user's ability to navigate your site with their keyboard or accessibility software. Some users report that setting tabindex to -1 resolves this issue (see comments in previous link).

🌐
DhiWise
dhiwise.com › post › how-does-react-listen-for-keypress-events-an-essential-guide
How React Listen for Keypress Events
May 24, 2024 - The onKeyUp event is triggered when a user releases a key. It is useful for scenarios where you want to ensure that the key press action is complete. Here's an example of using onKeyUp in a React component:
🌐
React
legacy.reactjs.org › docs › events.html
SyntheticEvent – React
onKeyDown onKeyPress onKeyUp · Properties: boolean altKey number charCode boolean ctrlKey boolean getModifierState(key) string key number keyCode string locale number location boolean metaKey boolean repeat boolean shiftKey number which · The key property can take any of the values documented in the DOM Level 3 Events spec. Event names: onFocus onBlur · These focus events work on all elements in the React DOM, not just form elements.
🌐
GitHub
github.com › facebook › react › issues › 25888
As `onKeyPress` is deprecated, what is its replacement ? · Issue #25888 · facebook/react
December 15, 2022 - React version: 18 · I have attached the link to codeSandbox for the frontend of payment method. You check by replacing onKeyPress with onKeyDown or onKeyUp, function won't work as required. https://codesandbox.io/s/success-dialoge-forked-sawan-qn3mgr?file=/src/component/CardDetails/CardDetails.js ·
Author   ProPhycient5