ifelsething logoifelsething

How to Automatically Focus on Next React Native TextInput?

Published On: 2024-02-19
Posted By: Harish

How to Automatically Focus on Next React Native TextInput

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.

Share is Caring

Related Posts