Keyboard Key Press Events of React Native TextInput
Published On: 2024-04-11
Posted By: Harish

Like press events of text input, we can also get the key press events of text input using onKeyPress callback.
This callback returns the event with the key details. Please note that this callback only works for soft keyboard and not for hardware keyboard.
Let's see this callback in action.
Create A New Project
Create a new react-native project by using npx. Check documentation for creating a new react native project.
npx react-native@latest init TextInputRN
Example Implementation
We will create a simple text input for a name.
Import the TextInput
component in the App.tsx
file and add basic required props for name.
Now add onKeyPress
callback to the name input.
//App.tsx
import { TextInput } from 'react-native';
...
<TextInput
style={styles.input}
keyboardType='default'
autoCorrect={false}
autoCapitalize="none"
placeholder='Enter Name'
placeholderTextColor='gray'
onKeyPress={event => {
console.log(event.nativeEvent);
}}
/>
...
Run the app,
#for Android
npx react-native run-android
#for ios
npx react-native run-ios
After rendering, enter text inside text input and check logs. You will see output similar to below log for android devices.
LOG {"key": "i"}
LOG {"key": "f"}
LOG {"key": "e"}
LOG {"key": "l"}
LOG {"key": "s"}
LOG {"key": "e"}
LOG {"key": "t"}
LOG {"key": "h"}
LOG {"key": "i"}
LOG {"key": "n"}
LOG {"key": "g"}
From the above log for android, we can see that the pressed key is showing up in the log. So, every time a key is pressed, onKeyPress callback returns an event with pressed key details.

For iOS, output is similar to android but has extra properties.
LOG {"eventCount": 0, "key": "i", "target": 389}
LOG {"eventCount": 1, "key": "f", "target": 389}
LOG {"eventCount": 2, "key": "e", "target": 389}
LOG {"eventCount": 3, "key": "l", "target": 389}
LOG {"eventCount": 4, "key": "s", "target": 389}
LOG {"eventCount": 5, "key": "e", "target": 389}
LOG {"eventCount": 6, "key": "t", "target": 389}
LOG {"eventCount": 7, "key": "h", "target": 389}
LOG {"eventCount": 8, "key": "i", "target": 389}
LOG {"eventCount": 9, "key": "n", "target": 389}
LOG {"eventCount": 10, "key": "g", "target": 389}
Sometimes, two events are fired on the text input key press in iOS devices. One correct key event followed by a backspace event is fired. I encountered this problem for iOS devices.
As a workaround, I've written a function with a global variable which checks the timestamp and assigns it to the global variable for the first event and will assign a 0
for the immediately followed backspace event.
Haven't tested for the production, but for the sake of this post, I'm using that workaround.
...
const onKeyPressForiOS = useCallback((event: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
const eventTimestamp = event.timeStamp
const nativeEvent = event.nativeEvent;
if (timestamp == 0) {
if (nativeEvent.key === 'Backspace') {
setKeyPress(nativeEvent);
return;
}
timestamp = eventTimestamp;
setKeyPress(nativeEvent);
} else {
timestamp = 0;
}
}, []);
...

Complete code of our example,
//App.tsx
import React, { useCallback, useState } from "react";
import {
Text,
StyleSheet,
TextInput,
SafeAreaView,
StatusBar,
View,
TextInputKeyPressEventData,
NativeSyntheticEvent,
Platform
} from "react-native";
export default function App() {
let timestamp = 0;
const [keyPress, setKeyPress] = useState<TextInputKeyPressEventData | undefined>();
const onKeyPressForiOS = useCallback((event: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
const eventTimestamp = event.timeStamp
const nativeEvent = event.nativeEvent;
if (timestamp == 0) {
if (nativeEvent.key === 'Backspace') {
setKeyPress(nativeEvent);
return;
}
timestamp = eventTimestamp;
setKeyPress(nativeEvent);
} else {
timestamp = 0;
}
}, []);
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'white' }}>
<StatusBar
barStyle="dark-content"
/>
<View style={styles.container} >
<Text style={styles.text}>
ifelsething.com
</Text>
<Text style={styles.text}>
text input keyboard key press events
</Text>
<TextInput
style={styles.input}
keyboardType='default'
placeholder='Enter Name'
placeholderTextColor='gray'
autoCorrect={false}
autoCapitalize="none"
onKeyPress={event => {
if(Platform.OS == 'ios') {
onKeyPressForiOS(event);
} else {
console.log("Key Press: ", event.nativeEvent)
setKeyPress(event.nativeEvent);
}
}}
/>
<Text style={styles.text}>
Output: {keyPress ? JSON.stringify(keyPress) : 'No Key Pressed'}
</Text>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
margin: 10,
gap: 20
},
input: {
borderColor: 'blue',
borderRadius: 10,
borderWidth: 1,
fontSize: 15,
padding: 10,
color: 'black',
},
text: {
fontSize: 15,
color: 'black',
fontStyle: 'italic'
},
});