react-nativereact-navigationpressable

How can i avoid hiding the keyboard when the onPress event(Pressable) is triggered?


My React Native app has a search screen(Page A) that goes back to the previous page when hiding the keyboard; Clicking on the search results will take you to the search results page(Page B). The problem is that clicking on a search result hides the keyboard, making the KeyboardDidHide event activated. The KeyboardDidHide event will cause a return to the previous page, causing the jump to page B to never be executed.

Is there a way to prevent hiding the keyboard when I press on another pressable component so that the KeyboardDidHide event doesn't fire

Here are the Code:

const Search: FC = () => {
  // state, refs
  const navigation = useNavigation();
  const [inputText, setInputText] = useState('');
  const _inputText = useDeferredValue(inputText);
  const [searchResult] = useSearchItem(_inputText);
  // KeyboardHide Detector
  useEffect(() => {
    const keyboardHideSubscription = Keyboard.addListener(
      'keyboardDidHide',
      () => {
        navigation.goBack();
      },
    );
    return () => {
      keyboardHideSubscription.remove();
    };
  }, []);
  return (
    <View>
      <View>
        <View>
          <ScrollView showsVerticalScrollIndicator={false}>
            {searchResult.map(result => (
              <Fragment key={result.id}>
                <List.ItemContent
                  onPress={e => {
                    navigation.navigate('Detail', {
                      itemDetail: result,
                    });
                  }}>
                  <Text>{result.name}</Text>
                </List.ItemContent>
              </Fragment>
            ))}
          </ScrollView>
        </View>
      </View>
      <KeyboardAvoidingView behavior="padding">
        <Shadow>
          <View>
            <SearchInput autoFocus value={inputText} onChange={setInputText} />
          </View>
        </Shadow>
      </KeyboardAvoidingView>
    </View>
  );
};

Solution

  • Make use of the Keyboard.dismiss() to explicitly dismiss the keyboard when needed.

    import { Keyboard } from 'react-native';
    
    const Search: FC = () => {
      // state, refs
      const navigation = useNavigation();
      const [inputText, setInputText] = useState('');
      const _inputText = useDeferredValue(inputText);
      const [searchResult] = useSearchItem(_inputText);
    
      const handleSearchResultPress = (result) => {
        Keyboard.dismiss(); // Dismiss the keyboard explicitly
        navigation.navigate('Detail', {
          gatheringItem: result,
        });
      };
    
      // KeyboardHide Detector
      useEffect(() => {
        const keyboardHideSubscription = Keyboard.addListener(
          'keyboardDidHide',
          () => {
            navigation.goBack();
          },
        );
        return () => {
          keyboardHideSubscription.remove();
        };
      }, []);
    
      return (
        <View>
          <View>
            <ScrollView showsVerticalScrollIndicator={false}>
              {searchResult.map(result => (
                <Fragment key={result.id}>
                  <List.ItemContent
                    icon={
                      <Icon
                        as={ExternalLinkIcon}
                        w={px2DpX(16)}
                        h={px2DpX(16)}
                      />
                    }
                    onPress={() => handleSearchResultPress(result)}>
                    <Text>{result.name}</Text>
                  </List.ItemContent>
                  <View key={`divider-${result.id}`} />
                </Fragment>
              ))}
            </ScrollView>
          </View>
          <KeyboardAvoidingView behavior="padding">
            <Shadow
              style={styles.panelWrapper}
              startColor={colorMode === 'light' ? '#00000020' : '#00000000'}>
              <View>
                <SearchInput autoFocus value={inputText} onChange={setInputText} />
              </View>
            </Shadow>
          </KeyboardAvoidingView>
        </View>
      );
    }