How to hide the keyboard in React Native on tapping outside of TextInput

How to hide the keyboard in React Native on tapping outside of TextInput:

This is a common problem and expected behavior in a mobile application. Suppose we have multiple TextInput components in a row and we need to hide the keyboard if the user clicks on anywhere outside.

This can be implemented in different ways in React Native. In this post, I will show you two different ways to solve this problem with a mini React Native project.

Method 1: By using a ScrollView:

We can simply add the items in a ScrollView and it will handle the keyboard automatically, i.e. if the user taps anywhere on ScrollView that is not a TextInput, the keyboard will be hidden.

Let’s try it with a simple project. Create one basic React Native project and replace the App.tsx file with the following:

import React from "react";
import {
  SafeAreaView,
  ScrollView,
  StyleSheet,
  TextInput,
  View,
  Button,
} from "react-native";

function App(): React.JSX.Element {
  return (
    <SafeAreaView>
      <ScrollView
        style={styles.scrollStyle}
        contentContainerStyle={styles.containerStyle}
      >
        <View style={styles.headerView} />
        <TextInput style={styles.input} />
        <TextInput style={styles.input} />
        <View style={styles.buttonView}>
          <Button title="click me" />
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  containerStyle: {
    alignItems: "center",
    flexGrow: 1,
  },
  scrollStyle: {
    height: "100%",
  },
  headerView: { height: 100, width: "80%", margin: 10, backgroundColor: "red" },
  input: {
    width: 300,
    margin: 10,
    borderWidth: 1,
    padding: 10,
    fontSize: 20,
  },
  buttonView: { width: 200 },
});

export default App;

This screen has one ScrollView with one View, two TextInput components and one more Button in a column. If you run this app, it will load the following screen:

React Native hide keyboard on clicking outside of TextInput

If you click outside the TextInput, it will hide the keyboard.

Method 2: By using the Keyboard module:

The problem with the above method is that it will hide the keyboard even if we click on the Button. If you click on the button, it will hide the keyboard and on the second click it will click on the button. One way to fix this is by passing keyboardShouldPersistTaps='handled' props to the ScrollView. It will not hide the keyboard if we click on any component of the ScrollView.

React Native provides a module to handle and listen to keyboard events. It has one method called dismiss to dismiss the keyboard manually.

We can use a TouchableWithoutFeedback as the parent component and call this method on onPress prop.

import React from "react";
import {
  SafeAreaView,
  TouchableWithoutFeedback,
  StyleSheet,
  TextInput,
  View,
  Button,
  Keyboard,
} from "react-native";

function App(): React.JSX.Element {
  return (
    <SafeAreaView>
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <View style={styles.parent}>
          <View style={styles.headerView} />
          <TextInput style={styles.input} />
          <TextInput style={styles.input} />
          <View style={styles.buttonView}>
            <Button title="click me" />
          </View>
        </View>
      </TouchableWithoutFeedback>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  parent: {
    height: "100%",
    alignItems: "center",
  },
  headerView: { height: 100, width: "80%", margin: 10, backgroundColor: "red" },
  input: {
    width: 300,
    margin: 10,
    borderWidth: 1,
    padding: 10,
    fontSize: 20,
  },
  buttonView: { width: 200 },
});

export default App;

It will hide the keyboard if the user taps anywhere outside the TextInput components. The button click will not hide the keyboard. It will click on the button.

By using a HOC:

We can use a higher order component or HOC to take the component as its child. We can write it as below in TypeScript:

type KeyboardDismissTouchableProps = {
  children: React.ReactNode,
};

const KeyboardDismissTouchable = ({
  children,
}: KeyboardDismissTouchableProps) => (
  <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
    {children}
  </TouchableWithoutFeedback>
);

Use it in any other file:

function App(): React.JSX.Element {
  return (
    <SafeAreaView>
      <KeyboardDismissTouchable>
        <View style={styles.parent}>
          <View style={styles.headerView} />
          <TextInput style={styles.input} />
          <TextInput style={styles.input} />
          <View style={styles.buttonView}>
            <Button title="click me" />
          </View>
        </View>
      </KeyboardDismissTouchable>
    </SafeAreaView>
  );
}

It will work similarly to the previous example.

You might also like: