https://github.com/tlow92/expo-key-event
Provides an interface for reading key events such as from external bluetooth keyboards on Android, iOS and Web.
https://github.com/tlow92/expo-key-event
expo expo-module key-event key-events react-native
Last synced: 6 months ago
JSON representation
Provides an interface for reading key events such as from external bluetooth keyboards on Android, iOS and Web.
- Host: GitHub
- URL: https://github.com/tlow92/expo-key-event
- Owner: tlow92
- Created: 2024-12-29T21:20:39.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-13T20:51:43.000Z (over 1 year ago)
- Last Synced: 2025-03-27T02:11:58.449Z (over 1 year ago)
- Topics: expo, expo-module, key-event, key-events, react-native
- Language: TypeScript
- Homepage:
- Size: 5.58 MB
- Stars: 18
- Watchers: 3
- Forks: 4
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
Expo-key-event
Interface for reading key events from external devices such as Bluetooth keyboards/gamepads.
Getting started
·
Report Bug
iOS
Android
Web
## Supported platforms
- iOS
- Android
- Web
- macOS (Mac Catalyst & react-native-macos)
## Requirements
Expo SDK >= 52
## Getting started
`npm i expo-key-event`
## Usage
#### Basic
Automatic listening: Key events are listened to as soon as `MyComponent` is mounted.
```tsx
import { useKeyEvent } from "expo-key-event";
import { Text } from "react-native";
export function MyComponent() {
const { keyEvent } = useKeyEvent();
return {keyEvent?.key};
}
```
#### Control listening
Manual listening: Key events are listened to when `startListening` is called.
```tsx
import { useKeyEvent } from "expo-key-event";
import { Text, View } from "react-native";
export function MyComponent() {
// deprecated way
// const { keyEvent, startListening, stopListening } = useKeyEvent(false);
// new way
const { keyEvent, keyReleaseEvent, startListening, stopListening } =
useKeyEvent({ listenOnMount: false });
return (
{keyEvent?.key}
startListening()} />
stopListening()} />
);
}
```
#### Using event listener
Handling state yourself: If you want to handle the state yourself or don't need the state at all, you can use the `useKeyEventListener` hook instead of the `useKeyEvent` hook.
```tsx
import { KeyPressEvent, useKeyEventListener } from "expo-key-event";
import { Text, View } from "react-native";
export function MyComponent() {
const [keyEvent, setKeyEvent] = useState();
// deprecated way
// const { startListening, stopListening } = useKeyEventListener((event) => {
// setKeyEvent(event);
// }, automaticControl);
// new way
const { startListening, stopListening } = useKeyEventListener(
(event) => {
setKeyEvent(event);
},
{
listenOnMount: automaticControl,
}
);
return (
{keyEvent?.key}
startListening()} />
stopListening()} />
);
}
```
#### Modifier keys
Using modifier keys: Key events include modifier key states (shift, ctrl, alt, meta) and repeat information when `captureModifiers` is enabled.
```tsx
import { useKeyEvent } from "expo-key-event";
import { Text, View } from "react-native";
export function MyComponent() {
const { keyEvent } = useKeyEvent({
listenOnMount: true,
captureModifiers: true, // Enable modifier key capture
});
return (
Key: {keyEvent?.key}
Shift: {keyEvent?.shiftKey ? "Yes" : "No"}
Ctrl: {keyEvent?.ctrlKey ? "Yes" : "No"}
Alt: {keyEvent?.altKey ? "Yes" : "No"}
Meta: {keyEvent?.metaKey ? "Yes" : "No"}
Repeat: {keyEvent?.repeat ? "Yes" : "No"}
);
}
```
#### Modifier key combinations
Checking for specific key combinations:
```tsx
import { useState } from "react";
import { KeyPressEvent, useKeyEventListener } from "expo-key-event";
import { Text } from "react-native";
export function MyComponent() {
const [message, setMessage] = useState("");
useKeyEventListener(
(event: KeyPressEvent) => {
// Check for Cmd+S (macOS) or Ctrl+S (Windows/Linux)
if (event.key === "KeyS" && (event.metaKey || event.ctrlKey)) {
setMessage("Save shortcut pressed!");
}
// Check for Shift+Enter
else if (event.key === "Enter" && event.shiftKey) {
setMessage("New line!");
}
// Check for Alt+Arrow
else if (event.key === "ArrowRight" && event.altKey) {
setMessage("Navigate forward!");
}
},
{
listenOnMount: true,
captureModifiers: true, // Required to receive modifier key states
}
);
return {message};
}
```
## Run example app
`cd example`
`npm run ios` / `npm run android` / `npm run web`
## Troubleshooting
### \_expo.useEvent is not a function
This is most likely due to using Expo SDK lower than 52. `useEvent` was introduced in SDK 52.
### Error: Cannot find native module 'ExpoKeyEvent'
Make sure to use a development build and not `Expo Go`.
See https://docs.expo.dev/guides/local-app-development/ for more details.
In short: Use `npx expo run:ios` instead of `npx expo start` (make sure bundleIdentifier is set in `app.json`).
### Key events are not registered in iOS simulator
Make sure that hardware keyboard is connected to the simulator.

### Key events are not registered in Android emulator
Since the Android emulator does not support USB or Bluetooth, you need to use a physical device so that key events can be registered.
Another option is to use `adb` to send key events to the emulator.
e.g. `adb shell input keyevent 10`
## How it works
This module translates the [Apple UIKit](https://developer.apple.com/documentation/uikit/uikeyboardhidusage) and [Android KeyEvent](https://developer.android.com/reference/android/view/KeyEvent) constants to a common set of key event types matching the ones from [Web](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code).