How to Focus Previous React Native TextInput on Backspace?
Published On: 2024-02-20
Posted By: Harish

We have seen a way to focus on the next text input after entering a value to the current input. We considered a simple OTP validation as an example. This post is a continuation of that post. Check the first post HERE.
In this post, we will see a way to focus on previous text input on deletion of value from current input. We will track the Backspace
key event to focus on previous input.
Add onKeyPress Callback
We can get a backspace event with the help of onKeyPress
callback. So, add onKeyPress callback to second, third and fourth text inputs and get the type of the key event.
For checking event type, we will create a new function called handleKeyPress
and pass to every text input's onKeyPress callback.
...
const handleKeyPress = (e: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
const key = e.nativeEvent.key;
return key === "Backspace" ? true : false;
};
...
<TextInput
...
onKeyPress={(e) => {
const isBack = handleKeyPress(e);
}}
...
/>
...
Function handleKeyPress
returns true if the occurred event is Backspace
. If not, returns false.
As we want to focus on previous text input on the backspace event, we check for truthy and use the focus()
method to shift focus on to the previous field.
...
//This is the second input which will focus on the first input after deleting the second input's value.
<TextInput
...
onKeyPress={(e) => {
const isBack = handleKeyPress(e);
if(isBack) {
firstRef.current.focus();
}
}}
...
/>
...
Last text input will shift to the previous input event even without clicking backspace. This weird behavior is because of occurring a backspace event with an actual event when the input is empty in onKeyPress callback.
As we are checking for a backspace event to focus on the previous field, this behavior will cause it to go back to the third field without pressing any backspace.
To clear this issue, I added a condition to focus on the current field if the event is not a backspace event. In our case, that is the fourth <TextInput>
field.
...
//This is the last input (fourth input) which will focus on the same input if the event is not a backspace event.
<TextInput
...
onKeyPress={(e) => {
const isBack = handleKeyPress(e);
if(isBack) {
thirdref.current.focus();
} else {
fourthRef.current.focus();
fourthRef.current.blur();
}
}}
...
/>
...
blur()
method of text input is the opposite of focus()
. It removes the focus and collapses the opened keyboard.
If you run the app, it will function like the video below.
Complete code,
//app.tsx
import { useRef } from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
NativeSyntheticEvent,
TextInputKeyPressEventData
} from "react-native";
export const App = () => {
const firstRef = useRef<any>(null);
const secondRef = useRef<any>(null);
const thirdRef = useRef<any>(null);
const fourthRef = useRef<any>(null);
const onKeyPress = (e: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
const key = e.nativeEvent.key;
return key === "Backspace" ? true : false;
};
return (
<View style={styles.container}>
<Text style={styles.text}>
ifelsething.com
</Text>
<Text style={styles.text}>
Automatically focus on previous text input on backspace.
</Text>
<View style={styles.block}>
<TextInput
maxLength={1}
style={styles.input}
ref={firstRef}
textAlign='center'
autoFocus={true}
showSoftInputOnFocus={true}
keyboardType='numeric'
onChangeText={(t: string) => {
if(!t) return;
console.log("First: ", t)
secondRef.current.focus();
}}
/>
<TextInput
maxLength={1}
ref={secondRef}
style={styles.input}
textAlign='center'
keyboardType='numeric'
onKeyPress={(e) => {
const isBack = onKeyPress(e);
if(isBack) {
firstRef.current.focus();
}
}}
onChangeText={(t: string) => {
if(!t) return;
console.log("Second: ", t)
thirdRef.current.focus();
}}
/>
<TextInput
maxLength={1}
ref={thirdRef}
style={styles.input}
textAlign='center'
keyboardType='numeric'
onKeyPress={(e) => {
const isBack = onKeyPress(e);
if(isBack) {
secondRef.current.focus();
}
}}
onChangeText={(t: string) => {
if(!t) return;
console.log("Third: ", t)
fourthRef.current.focus();
}}
/>
<TextInput
maxLength={1}
ref={fourthRef}
style={styles.input}
textAlign='center'
keyboardType='numeric'
onKeyPress={(e) => {
const isBack = onKeyPress(e);
if(isBack) {
thirdRef.current.focus();
} else {
fourthRef.current.focus();
fourthRef.current.blur();
}
}}
onChangeText={(t: string) => {
if(!t) return;
console.log("Fourth: ", t)
}}
/>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
margin: 10,
gap: 20
},
input: {
width: 50,
height: 50,
borderColor: 'blue',
borderWidth: 1,
borderRadius: 50,
padding: 10,
fontSize: 20,
color: 'black',
},
text: {
fontSize: 15,
color: 'black',
fontStyle: 'italic'
},
block: {
flexGrow: 1,
flexDirection: 'row',
gap: 10,
justifyContent: 'center'
}
});