skip to Main Content

This must be trivial but I can’t seem to figure out.

Context: I have a custom component to hide the keyboard everytime the user taps somewhere on the screen.

HideKeyboard.tsx

import {  TouchableWithoutFeedback, Keyboard, } from 'react-native'
import React from 'react'

export interface HideKeyboardProps {
    children: React.ReactNode;
}

export default function HideKeyboard(props: HideKeyboardProps) {
    return (
        <TouchableWithoutFeedback onPress={() => { Keyboard.dismiss(); }}>
            {props.children}
        </TouchableWithoutFeedback>
    )
}

This works fine, but the problem arises when the user taps on a button on the screen. The expected behaviour would be – the keyboard dismisses and the click handler of the button gets executed.

But, because of the HideKeyboard control, the initial tap gets captured and is used to dismiss the keyboard and so the user has to tap again.

Is there a way to tackle this? Can we somehow execute the event in the onPress handler?

2

Answers


  1. One possible way to ensure the event gets bubbled when using TouchableWithoutFeedback is to use the onPressOut prop instead of the onPress prop. For example, you can change your HideKeyboard component to something like this:

    export default function HideKeyboard(props: HideKeyboardProps) {
        return (
            <TouchableWithoutFeedback onPressOut={() => { Keyboard.dismiss(); }}>
                {props.children}
            </TouchableWithoutFeedback>
        )
    }
    

    This will dismiss the keyboard when the user releases the touch, but will also allow the event to bubble up to the button’s
    onPress handler.

    Login or Signup to reply.
  2. I’d change the behavior so that the tap event is not "consumed" by the TouchableWithoutFeedback. Wrap your components with View instead of TouchableWithoutFeedback and use the onStartShouldSetResponder property of the View to detect touch events.

    How to modify the HideKeyboard component:

    import { View, Keyboard } from 'react-native';
    import React from 'react';
    
    export interface HideKeyboardProps {
      children: React.ReactNode;
    }
    
    export default function HideKeyboard(props: HideKeyboardProps) {
      return (
        <View
          onStartShouldSetResponder={() => {
            Keyboard.dismiss();
            return false; // Continue propagating the event
          }}
        >
          {props.children}
        </View>
      );
    }
    

    By returning false from the onStartShouldSetResponder handler, you’re telling React Native to continue propagating the touch event to other views. Button click handler should be executed as expected.

    I think this gives you the behavior you’re looking for – dismissing the keyboard when the user taps somewhere on the screen without interfering with button clicks.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search