How to Automatically Focus on Next React Native TextInput?
Published On: 2024-02-19
Posted By: Harish

We have seen a way to initially focus on a <TextInput>
field using an autoFocus prop or programmatically by using useRef hook.
In this article, we will see a way to automatically focus on the next text input field. Common usage can be seen in the OTP verification screens
, where the user enters the received OTP to validate. So, we will create something similar in this post.
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
Add TextInput Fields
Let's import TextInput
from react and add four <TextInput>
fields in the app.tsx
file.
Generally it is a bad practice to repeat the code unnecessarily. For this article's purpose, I'm taking four text inputs for clear understanding.
Add Props to TextInputs
The focused input for initial rendering will be the first text input field, so add autoFocus
prop to the first field. And also add showSoftInputOnFocus={true}
to show the keyboard on load. This is not needed but it's good to have.
As we are replicating the OTP screen, let's add maxLength={1}
because for OTP, each input is limited to one number. Below mentioned props in code are similar to all four text inputs other than autoFocus and showSoftInputOnFocus props.
//app.tsx
import {TextInput} from 'react-native';
...
<TextInput
maxLength={1}
style={styles.input}
textAlign='center'
autoFocus={true}
showSoftInputOnFocus={true}
keyboardType='numeric'
/>
...
useRef Hook
This is the main part for jumping to next input automatically. We create four refs for four input fields and use text input's focus()
method to focus on the next field.
Create four references using useRef
hook and pass to their text input fields in ref
prop.
import {useRef} from 'react';
import {TextInput} 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);
...
...
<TextInput
ref={firstRef}
...
/>
...
...
We have references to the text input fields, now we have to focus on the next input field when a number is entered in the previous field. This can be achieved with onChangeText
callback to get the entered number value and to focus on the next input field.
Add onChangeText
callback to all input fields.
<TextInput
...
...
onChangeText={(t: string) => {
if(!t) return;
console.log("First: ", t)
}}
/>
Now we will call the next input’s focus method so that it gets focused after getting the first input’s value. Similarly, we have to add to other inputs.
<TextInput
...
...
onChangeText={(t: string) => {
if(!t) return;
console.log("First: ", t)
secondRef.current.focus();
}}
/>
Please note that we limited the text input's length to 1
character, so this directly gets focused on the next field when a number is entered. If there is no limitation, we have to write conditions to focus on the next field based on our requirement.
Now, run the app, to get results like in the video below.
Complete code,
//app.tsx
import { useRef } from 'react';
import {
View,
Text,
StyleSheet,
TextInput
} 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);
return (
<View style={styles.container}>
<Text style={styles.text}>
ifelsething.com
</Text>
<Text style={styles.text}>
Automatically focus on next text input after entering a number.
</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'
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'
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'
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'
}
});
Note:
- There will be a weird behavior of calling the onChangeText callback twice for empty input fields. This is due to calling references to focus on the next fields. For this tutorial approach, this can be ignored.