React Keyboard Events

In the last lesson you learned about React Form Events, so you can read what a user types. This lesson is about catching key presses like Enter and Escape, so you can run an action the moment a specific key goes down.

🤔 Why do we need keyboard events?

Here’s the pain. Users expect keys to do things, and a form with only a button feels broken to them.

  • You build a search box. The user types a query, then presses Enter like they always do.
  • Nothing happens. They have to move the mouse and click a button instead. Annoying, right?
  • Or you open a popup. The user hits Escape to close it, because that’s the normal way. But your popup just sits there.
  • These are small things, but they make an app feel slow and clumsy.

So the real problem is that people want to drive your app with the keyboard. Keyboard events let your component listen for key presses and react to them.

🧩 What are keyboard events?

A keyboard event is a signal React fires when the user presses or releases a key while an element is focused.

  • A keyboard event is just React telling you “a key was pressed” along with details about which key it was.
  • You listen for it with a prop like onKeyDown, the same way you used onClick.
  • React hands your function an event object, usually called e. Inside it is everything you need to know about the press.
  • The most useful piece is e.key. It holds the name of the key that was pressed, as text.

Think of it like a doorbell. When someone presses a key, the bell rings, and the event object is the note that says exactly which button they pushed.

⌨️ onKeyDown and onKeyUp

There are two main moments you can listen for. One is when the key goes down, the other is when it comes back up.

  • onKeyDown fires the instant a key is pressed down. This is the one you’ll use most of the time.
  • onKeyUp fires when the key is released. Useful when you care about the press ending, not starting.
  • For most actions like “submit on Enter”, onKeyDown is the right choice because it reacts immediately.

This input logs which key was pressed the moment it goes down.

function KeyLogger() {
const handleKeyDown = (e) => {
console.log("You pressed:", e.key);
};
return <input type="text" onKeyDown={handleKeyDown} />;
}

When you press the “a” key, e.key is "a". Press Enter and e.key is "Enter". Press Escape and it’s "Escape". So e.key gives you a plain, readable name for whatever was pressed.

onKeyPress is gone

You may see older code using onKeyPress. That one is deprecated, which means it’s old and you should not use it. Stick with onKeyDown and onKeyUp in modern React.

🔑 Reading e.key the right way

Now the important part. To know which key was pressed, read e.key, not old number codes.

  • e.key is a readable string like "Enter", "Escape", "a", or "ArrowUp". Easy to understand at a glance.
  • Older code used e.keyCode, a number like 13 for Enter. Nobody remembers what 13 means, and keyCode is deprecated too.
  • So always compare against the readable name. Check e.key === "Enter", never e.keyCode === 13.

This shows the old number-code way versus the modern e.key way.

const handleKeyDown = (e) => {
// ❌ Old and deprecated - what is 13 even?
if (e.keyCode === 13) {
console.log("Enter pressed");
}
// ✅ Modern and clear - reads like English
if (e.key === "Enter") {
console.log("Enter pressed");
}
};

Both versions try to detect Enter, but only the e.key one is correct for modern React. It reads like plain English, so anyone can tell what it checks.

🔎 Submit a search when Enter is pressed

Let’s build the real thing now. A search box that runs a search the moment the user presses Enter.

This input keeps its text in state, and presses Enter to fire the search.

import { useState } from "react";
function SearchBox() {
const [query, setQuery] = useState("");
const handleKeyDown = (e) => {
if (e.key === "Enter") {
console.log("Searching for:", query);
}
};
return (
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Search and press Enter"
/>
);
}

Let’s walk through what happens here.

  • useState("") holds the current text of the input in query, starting empty.
  • onChange updates query on every keystroke, so state always matches what’s typed.
  • onKeyDown runs handleKeyDown on every key press.
  • Inside it, if (e.key === "Enter") checks for just the Enter key. Other keys are ignored.
  • When Enter is pressed, you run your search using the current query.

Output

Searching for: react keyboard events

So the user types, hits Enter, and the search fires. No button click needed. That’s exactly the behaviour people expect.

🚪 Close a box when Escape is pressed

Same idea, different key. A common pattern is closing a popup when the user presses Escape.

This box shows when open, and Escape closes it.

import { useState } from "react";
function Popup() {
const [isOpen, setIsOpen] = useState(true);
const handleKeyDown = (e) => {
if (e.key === "Escape") {
setIsOpen(false);
}
};
if (!isOpen) return null;
return (
<input
type="text"
onKeyDown={handleKeyDown}
placeholder="Press Escape to close"
/>
);
}

Here’s the flow.

  • isOpen starts as true, so the box shows on screen.
  • onKeyDown checks e.key === "Escape" on every key press.
  • When Escape is pressed, setIsOpen(false) flips the state to closed.
  • if (!isOpen) return null then renders nothing, so the box disappears.

So one key press closes the box. The user gets the Escape behaviour they’re used to from every other app.

🎯 Keyboard events need focus

One thing trips people up here, so let’s be clear about it. Keyboard events only fire on the element that has focus.

  • An element has focus when it’s the active target for typing, like an input you clicked into.
  • Inputs, textareas, and buttons can take focus by default, so they catch keyboard events naturally.
  • A plain <div> cannot take focus on its own, so by default it never hears key presses.
  • To make a <div> focusable, give it tabIndex={0}. Now it can be focused and it will fire keyboard events.

This div can take focus and listen for keys because of tabIndex.

function Panel() {
const handleKeyDown = (e) => {
if (e.key === "Escape") {
console.log("Escape pressed inside the panel");
}
};
return (
<div tabIndex={0} onKeyDown={handleKeyDown}>
Click me first, then press Escape
</div>
);
}

Here’s why this works.

  • tabIndex={0} is what makes the div focusable in the first place.
  • Without it, you’d click the div and press Escape, and nothing would happen.
  • That’s because the div never had focus to begin with, so it never heard the key.

Focus first, then keys

If your keyboard handler “isn’t working”, check focus first. The element must be focused before it hears any key press. For a <div>, that almost always means you forgot tabIndex={0}.

🧩 What You’ve Learned

  • ✅ Keyboard events let your component react to key presses like Enter and Escape
  • onKeyDown fires when a key goes down, onKeyUp fires when it’s released
  • onKeyPress is deprecated, so use onKeyDown and onKeyUp instead
  • ✅ Read e.key to get a readable name like "Enter", "Escape", or "a"
  • ✅ Use e.key === "Enter", never the old deprecated e.keyCode === 13
  • ✅ A common pattern is submitting a search on Enter or closing a box on Escape
  • ✅ Keyboard events only fire on focused elements, and a <div> needs tabIndex={0} to take focus

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    Which property tells you which key was pressed in a modern React keyboard event?

    Why: e.key holds a readable name like "Enter" or "Escape". e.keyCode is the old, deprecated number-based way and should not be used in modern React.

  2. 2

    How do you check if the user pressed the Enter key?

    Why: Compare e.key against the readable name "Enter". The keyCode === 13 form is deprecated and harder to read.

  3. 3

    What is the status of onKeyPress in modern React?

    Why: onKeyPress is deprecated. Use onKeyDown for immediate reactions and onKeyUp for when a key is released.

  4. 4

    Why might a keyboard handler on a plain <div> never fire?

    Why: Keyboard events only fire on the focused element. A plain div cannot take focus by default, so adding tabIndex={0} makes it focusable and able to hear key presses.

🚀 What’s Next?

Now you can catch key presses and react to the exact key, like submitting on Enter or closing on Escape. Next you’ll handle the other big source of user input: the mouse, with clicks, hovers, and more.

React Mouse Events

Share & Connect