Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onPress not working on android #940

Open
jahanzaib5244 opened this issue Apr 15, 2024 · 16 comments
Open

onPress not working on android #940

jahanzaib5244 opened this issue Apr 15, 2024 · 16 comments
Labels

Comments

@jahanzaib5244
Copy link

onPress not working on android

i am using a map and GooglePlacesAutocomplete input on ios it is working perfectly but on android i am unable to pick the location .

Please provide a FULLY REPRODUCIBLE example.

Click to expand!
  const GooglePlacesInput: React.FC<PlaceInputProps> = ({onSelect, ref}) => {
return (
  <GooglePlacesAutocomplete
    ref={ref}
    fetchDetails={true}
    enablePoweredByContainer={false}
    disableScroll
    styles={{
      container: {
        marginHorizontal: Width(20),
        zIndex: 10000,
        flex: 1,
      },
      textInput: {
        color: colors.black,
      },
      listView: {
        backgroundColor: 'green',
        zIndex: 10000,
      },
    }}
    textInputProps={{
      cursorColor: colors.black,
      placeholderTextColor: colors.gery_dark,
    }}
    placeholder="Search"
    onPress={onSelect}
    query={{
      key: MAP_KEY,
      language: 'en',
    }}
    onFail={error => {
      console.log('onFail');
    }}
  />
);


<View style={styles.map_container}>
          <MapView
            ref={mapViewRef}
            provider={PROVIDER_GOOGLE} // remove if not using Google Maps
            style={[StyleSheet.absoluteFill, {zIndex: 0}]}
            region={region}
            onRegionChangeComplete={onRegionChangeComplete}
          />
          <View style={styles.autocomplete_input_container}>
            <GooglePlacesInput
              ref={inputRef}
              onSelect={(data, details) => {
                setGetAddress(false);
                const selectedRegion = {
                  ...region,
                  location: details?.formatted_address || '',
                  latitude:
                    details?.geometry?.location?.lat ??
                    userLocation?.latitude ??
                    31.4482849,
                  longitude:
                    details?.geometry?.location?.lng ??
                    userLocation?.longitude ??
                    74.3095673,
                };
                setAddress(details?.formatted_address || '');
                setRegion(selectedRegion);
                mapViewRef.current?.animateToRegion(selectedRegion, 1000);
                setvalue(pre => ({
                  ...pre,
                  location: details?.formatted_address || '',
                  latitude:
                    details?.geometry?.location?.lat ??
                    userLocation?.latitude ??
                    31.4482849,
                  longitude:
                    details?.geometry?.location?.lng ??
                    userLocation?.longitude ??
                    74.3095673,
                }));
              }}
            />
          </View>

          <Icon
            type={IconType.MaterialCommunityIcons}
            name="map-marker"
            size={Height(50)}
            color={colors.danger}
            style={styles.map_marker}
          />
        </View>
  

Please remember to remove you google API key from the code you provide here

Additional context

  • Library Version: 2.5.1
  • React Native Version: 0.72.5

Add any other context about the problem here, screenshots etc

@juzerdhinoj-dimiour
Copy link

Facing this issue as well. Any resolutions yet?

@jahanzaib5244
Copy link
Author

jahanzaib5244 commented Apr 27, 2024

index 99a2a13..6640f00 100644
--- a/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
+++ b/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
@@ -13,7 +13,6 @@ import React, {
 } from 'react';
 import {
   ActivityIndicator,
-  FlatList,
   Image,
   Keyboard,
   Platform,
@@ -22,8 +21,10 @@ import {
   StyleSheet,
   Text,
   TextInput,
+  TouchableOpacity,
   View,
 } from 'react-native';
+import { FlatList } from 'react-native-gesture-handler';
 
 const defaultStyles = {
   container: {
@@ -258,6 +259,7 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
   };
 
   const _onPress = (rowData) => {
+    console.log('pressed')
     if (rowData.isPredefinedPlace !== true && props.fetchDetails === true) {
       if (rowData.isLoading === true) {
         // already requesting
@@ -645,19 +647,11 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     return null;
   };
 
-  const _renderRow = (rowData = {}, index) => {
+  const _renderRow =useCallback((rowData = {}, index) => {
+    console.log('rendered')
     return (
-      <ScrollView
-        contentContainerStyle={
-          props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' }
-        }
-        scrollEnabled={props.isRowScrollable}
-        keyboardShouldPersistTaps={props.keyboardShouldPersistTaps}
-        horizontal={true}
-        showsHorizontalScrollIndicator={false}
-        showsVerticalScrollIndicator={false}
-      >
         <Pressable
+        key={Math.random().toString(36)}
           style={({ hovered, pressed }) => [
             props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' },
             {
@@ -682,9 +676,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
             {_renderRowData(rowData, index)}
           </View>
         </Pressable>
-      </ScrollView>
     );
-  };
+  },[props]);
+
 
   const _renderSeparator = (sectionID, rowID) => {
     if (rowID === dataSource.length - 1) {
@@ -785,46 +779,24 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     }
   };
 
-  const _getFlatList = () => {
-    const keyGenerator = () => Math.random().toString(36).substr(2, 10);
+  const _getFlatList =useCallback( () => {
    
     if (
-      supportedPlatform() &&
-      (stateText !== '' ||
-        props.predefinedPlaces.length > 0 ||
-        props.currentLocation === true) &&
+      stateText !== ''  &&
       listViewDisplayed === true
     ) {
       return (
-        <FlatList
-          nativeID='result-list-id'
-          scrollEnabled={!props.disableScroll}
-          style={[
-            props.suppressDefaultStyles ? {} : defaultStyles.listView,
-            props.styles.listView,
-          ]}
-          data={dataSource}
-          keyExtractor={keyGenerator}
-          extraData={[dataSource, props]}
-          ItemSeparatorComponent={_renderSeparator}
-          renderItem={({ item, index }) => _renderRow(item, index)}
-          ListEmptyComponent={
-            listLoaderDisplayed
-              ? props.listLoaderComponent
-              : stateText.length > props.minLength && props.listEmptyComponent
-          }
-          ListHeaderComponent={
-            props.renderHeaderComponent &&
-            props.renderHeaderComponent(stateText)
-          }
-          ListFooterComponent={_renderPoweredLogo}
-          {...props}
-        />
+        <View  style={{zIndex:0,}} >
+          {[...dataSource].slice(0,5).map((item,index)=>{
+            return _renderRow(item, index)
+          })}
+        </View>
+        
       );
     }
 
     return null;
-  };
+  },[dataSource]);
 
   let {
     onFocus,
@@ -835,6 +807,8 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     ...userProps
   } = props.textInputProps;
   const TextInputComp = InputComp || TextInput;
+  console.log('rendered')
+
   return (
     <View
       style={[
@@ -882,9 +856,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
           {_renderRightButton()}
         </View>
       )}
-      {props.inbetweenCompo}
+      {/* {props.inbetweenCompo} */}
       {_getFlatList()}
-      {props.children}
+      {/* {props.children} */}
     </View>
   );
 });

@juzerdhinoj-dimiour you can use this patch file and the issue will be resolved. I replaced Flatlist with map and it worked. Still not get why onPress was not working inside Flatlist

@juzerdhinoj-dimiour
Copy link

Will this disrupt the currently working iOS functionality?

index 99a2a13..6640f00 100644
--- a/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
+++ b/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
@@ -13,7 +13,6 @@ import React, {
 } from 'react';
 import {
   ActivityIndicator,
-  FlatList,
   Image,
   Keyboard,
   Platform,
@@ -22,8 +21,10 @@ import {
   StyleSheet,
   Text,
   TextInput,
+  TouchableOpacity,
   View,
 } from 'react-native';
+import { FlatList } from 'react-native-gesture-handler';
 
 const defaultStyles = {
   container: {
@@ -258,6 +259,7 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
   };
 
   const _onPress = (rowData) => {
+    console.log('pressed')
     if (rowData.isPredefinedPlace !== true && props.fetchDetails === true) {
       if (rowData.isLoading === true) {
         // already requesting
@@ -645,19 +647,11 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     return null;
   };
 
-  const _renderRow = (rowData = {}, index) => {
+  const _renderRow =useCallback((rowData = {}, index) => {
+    console.log('rendered')
     return (
-      <ScrollView
-        contentContainerStyle={
-          props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' }
-        }
-        scrollEnabled={props.isRowScrollable}
-        keyboardShouldPersistTaps={props.keyboardShouldPersistTaps}
-        horizontal={true}
-        showsHorizontalScrollIndicator={false}
-        showsVerticalScrollIndicator={false}
-      >
         <Pressable
+        key={Math.random().toString(36)}
           style={({ hovered, pressed }) => [
             props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' },
             {
@@ -682,9 +676,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
             {_renderRowData(rowData, index)}
           </View>
         </Pressable>
-      </ScrollView>
     );
-  };
+  },[props]);
+
 
   const _renderSeparator = (sectionID, rowID) => {
     if (rowID === dataSource.length - 1) {
@@ -785,46 +779,24 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     }
   };
 
-  const _getFlatList = () => {
-    const keyGenerator = () => Math.random().toString(36).substr(2, 10);
+  const _getFlatList =useCallback( () => {
    
     if (
-      supportedPlatform() &&
-      (stateText !== '' ||
-        props.predefinedPlaces.length > 0 ||
-        props.currentLocation === true) &&
+      stateText !== ''  &&
       listViewDisplayed === true
     ) {
       return (
-        <FlatList
-          nativeID='result-list-id'
-          scrollEnabled={!props.disableScroll}
-          style={[
-            props.suppressDefaultStyles ? {} : defaultStyles.listView,
-            props.styles.listView,
-          ]}
-          data={dataSource}
-          keyExtractor={keyGenerator}
-          extraData={[dataSource, props]}
-          ItemSeparatorComponent={_renderSeparator}
-          renderItem={({ item, index }) => _renderRow(item, index)}
-          ListEmptyComponent={
-            listLoaderDisplayed
-              ? props.listLoaderComponent
-              : stateText.length > props.minLength && props.listEmptyComponent
-          }
-          ListHeaderComponent={
-            props.renderHeaderComponent &&
-            props.renderHeaderComponent(stateText)
-          }
-          ListFooterComponent={_renderPoweredLogo}
-          {...props}
-        />
+        <View  style={{zIndex:0,}} >
+          {[...dataSource].slice(0,5).map((item,index)=>{
+            return _renderRow(item, index)
+          })}
+        </View>
+        
       );
     }
 
     return null;
-  };
+  },[dataSource]);
 
   let {
     onFocus,
@@ -835,6 +807,8 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     ...userProps
   } = props.textInputProps;
   const TextInputComp = InputComp || TextInput;
+  console.log('rendered')
+
   return (
     <View
       style={[
@@ -882,9 +856,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
           {_renderRightButton()}
         </View>
       )}
-      {props.inbetweenCompo}
+      {/* {props.inbetweenCompo} */}
       {_getFlatList()}
-      {props.children}
+      {/* {props.children} */}
     </View>
   );
 });

@juzerdhinoj-dimiour you can use this patch file and the issue will be resolved. I replaced Flatlist with map and it worked. Still not get why onPress was not working inside Flatlist

@jahanzaib5244
Copy link
Author

Will this disrupt the currently working iOS functionality?

index 99a2a13..6640f00 100644
--- a/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
+++ b/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
@@ -13,7 +13,6 @@ import React, {
 } from 'react';
 import {
   ActivityIndicator,
-  FlatList,
   Image,
   Keyboard,
   Platform,
@@ -22,8 +21,10 @@ import {
   StyleSheet,
   Text,
   TextInput,
+  TouchableOpacity,
   View,
 } from 'react-native';
+import { FlatList } from 'react-native-gesture-handler';
 
 const defaultStyles = {
   container: {
@@ -258,6 +259,7 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
   };
 
   const _onPress = (rowData) => {
+    console.log('pressed')
     if (rowData.isPredefinedPlace !== true && props.fetchDetails === true) {
       if (rowData.isLoading === true) {
         // already requesting
@@ -645,19 +647,11 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     return null;
   };
 
-  const _renderRow = (rowData = {}, index) => {
+  const _renderRow =useCallback((rowData = {}, index) => {
+    console.log('rendered')
     return (
-      <ScrollView
-        contentContainerStyle={
-          props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' }
-        }
-        scrollEnabled={props.isRowScrollable}
-        keyboardShouldPersistTaps={props.keyboardShouldPersistTaps}
-        horizontal={true}
-        showsHorizontalScrollIndicator={false}
-        showsVerticalScrollIndicator={false}
-      >
         <Pressable
+        key={Math.random().toString(36)}
           style={({ hovered, pressed }) => [
             props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' },
             {
@@ -682,9 +676,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
             {_renderRowData(rowData, index)}
           </View>
         </Pressable>
-      </ScrollView>
     );
-  };
+  },[props]);
+
 
   const _renderSeparator = (sectionID, rowID) => {
     if (rowID === dataSource.length - 1) {
@@ -785,46 +779,24 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     }
   };
 
-  const _getFlatList = () => {
-    const keyGenerator = () => Math.random().toString(36).substr(2, 10);
+  const _getFlatList =useCallback( () => {
    
     if (
-      supportedPlatform() &&
-      (stateText !== '' ||
-        props.predefinedPlaces.length > 0 ||
-        props.currentLocation === true) &&
+      stateText !== ''  &&
       listViewDisplayed === true
     ) {
       return (
-        <FlatList
-          nativeID='result-list-id'
-          scrollEnabled={!props.disableScroll}
-          style={[
-            props.suppressDefaultStyles ? {} : defaultStyles.listView,
-            props.styles.listView,
-          ]}
-          data={dataSource}
-          keyExtractor={keyGenerator}
-          extraData={[dataSource, props]}
-          ItemSeparatorComponent={_renderSeparator}
-          renderItem={({ item, index }) => _renderRow(item, index)}
-          ListEmptyComponent={
-            listLoaderDisplayed
-              ? props.listLoaderComponent
-              : stateText.length > props.minLength && props.listEmptyComponent
-          }
-          ListHeaderComponent={
-            props.renderHeaderComponent &&
-            props.renderHeaderComponent(stateText)
-          }
-          ListFooterComponent={_renderPoweredLogo}
-          {...props}
-        />
+        <View  style={{zIndex:0,}} >
+          {[...dataSource].slice(0,5).map((item,index)=>{
+            return _renderRow(item, index)
+          })}
+        </View>
+        
       );
     }
 
     return null;
-  };
+  },[dataSource]);
 
   let {
     onFocus,
@@ -835,6 +807,8 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
     ...userProps
   } = props.textInputProps;
   const TextInputComp = InputComp || TextInput;
+  console.log('rendered')
+
   return (
     <View
       style={[
@@ -882,9 +856,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
           {_renderRightButton()}
         </View>
       )}
-      {props.inbetweenCompo}
+      {/* {props.inbetweenCompo} */}
       {_getFlatList()}
-      {props.children}
+      {/* {props.children} */}
     </View>
   );
 });

@juzerdhinoj-dimiour you can use this patch file and the issue will be resolved. I replaced Flatlist with map and it worked. Still not get why onPress was not working inside Flatlist

No, it will not reflect the ios.

@juzerdhinoj-dimiour
Copy link

juzerdhinoj-dimiour commented Apr 27, 2024

@jahanzaib5244 Instead of the change list, can you please share the actual file? It will be a better reference point.

@jahanzaib5244
Copy link
Author

@jahanzaib5244 Instead of the change list, can you please share the actual file? It will be a better reference point.

import PropTypes from 'prop-types';
import Qs from 'qs';
import React, {
  forwardRef,
  useMemo,
  useEffect,
  useImperativeHandle,
  useRef,
  useState,
  useCallback,
} from 'react';
import {
  ActivityIndicator,
  Image,
  Keyboard,
  Platform,
  Pressable,
  StyleSheet,
  Text,
  TextInput,
  View,
} from 'react-native';

const defaultStyles = {
  container: {
    flex: 1,
  },
  textInputContainer: {
    flexDirection: 'row',
  },
  textInput: {
    backgroundColor: '#FFFFFF',
    height: 44,
    borderRadius: 5,
    paddingVertical: 5,
    paddingHorizontal: 10,
    fontSize: 15,
    flex: 1,
    marginBottom: 5,
  },
  listView: {},
  row: {
    backgroundColor: '#FFFFFF',
    padding: 13,
    minHeight: 44,
    flexDirection: 'row',
  },
  loader: {
    flexDirection: 'row',
    justifyContent: 'flex-end',
    height: 20,
  },
  description: {},
  separator: {
    height: StyleSheet.hairlineWidth,
    backgroundColor: '#c8c7cc',
  },
  poweredContainer: {
    justifyContent: 'flex-end',
    alignItems: 'center',
    borderBottomRightRadius: 5,
    borderBottomLeftRadius: 5,
    borderColor: '#c8c7cc',
    borderTopWidth: 0.5,
  },
  powered: {},
};

export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
  let _results = [];
  let _requests = [];

  const hasNavigator = () => {
    if (navigator?.geolocation) {
      return true;
    } else {
      console.warn(
        'If you are using React Native v0.60.0+ you must follow these instructions to enable currentLocation: https://git.io/Jf4AR',
      );
      return false;
    }
  };

  const buildRowsFromResults = useCallback(
    (results, text) => {
      let res = [];
      const shouldDisplayPredefinedPlaces = text
        ? results.length === 0 && text.length === 0
        : results.length === 0;
      if (
        shouldDisplayPredefinedPlaces ||
        props.predefinedPlacesAlwaysVisible === true
      ) {
        res = [
          ...props.predefinedPlaces.filter(
            (place) => place?.description.length,
          ),
        ];

        if (props.currentLocation === true && hasNavigator()) {
          res.unshift({
            description: props.currentLocationLabel,
            isCurrentLocation: true,
          });
        }
      }

      res = res.map((place) => ({
        ...place,
        isPredefinedPlace: true,
      }));

      return [...res, ...results];
    },
    [
      props.currentLocation,
      props.currentLocationLabel,
      props.predefinedPlaces,
      props.predefinedPlacesAlwaysVisible,
    ],
  );

  const getRequestUrl = useCallback((requestUrl) => {
    if (requestUrl) {
      if (requestUrl.useOnPlatform === 'all') {
        return requestUrl.url;
      }
      if (requestUrl.useOnPlatform === 'web') {
        return Platform.select({
          web: requestUrl.url,
          default: 'https://maps.googleapis.com/maps/api',
        });
      }
    } else {
      return 'https://maps.googleapis.com/maps/api';
    }
  }, []);

  const getRequestHeaders = (requestUrl) => {
    return requestUrl?.headers || {};
  };

  const setRequestHeaders = (request, headers) => {
    Object.keys(headers).map((headerKey) =>
      request.setRequestHeader(headerKey, headers[headerKey]),
    );
  };

  const [stateText, setStateText] = useState('');
  const [dataSource, setDataSource] = useState(buildRowsFromResults([]));
  const [listViewDisplayed, setListViewDisplayed] = useState(
    props.listViewDisplayed === 'auto' ? false : props.listViewDisplayed,
  );
  const [url, setUrl] = useState(getRequestUrl(props.requestUrl));
  const [listLoaderDisplayed, setListLoaderDisplayed] = useState(false);

  const inputRef = useRef();

  useEffect(() => {
    setUrl(getRequestUrl(props.requestUrl));
  }, [getRequestUrl, props.requestUrl]);

  useEffect(() => {
    // This will load the search results after the query object ref gets changed
    _handleChangeText(stateText);
    return () => {
      _abortRequests();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [props.query]);

  useEffect(() => {
    // Update dataSource if props.predefinedPlaces changed
    setDataSource(buildRowsFromResults([]));
  }, [buildRowsFromResults, props.predefinedPlaces]);

  useImperativeHandle(ref, () => ({
    setAddressText: (address) => {
      setStateText(address);
    },
    getAddressText: () => stateText,
    blur: () => inputRef.current.blur(),
    focus: () => inputRef.current.focus(),
    isFocused: () => inputRef.current.isFocused(),
    clear: () => inputRef.current.clear(),
    getCurrentLocation,
  }));

  const requestShouldUseWithCredentials = () =>
    url === 'https://maps.googleapis.com/maps/api';

  const _abortRequests = () => {
    _requests.map((i) => {
      i.onreadystatechange = null;
      i.abort();
    });
    _requests = [];
  };

  const supportedPlatform = () => {
    if (Platform.OS === 'web' && !props.requestUrl) {
      console.warn(
        'This library cannot be used for the web unless you specify the requestUrl prop. See https://git.io/JflFv for more for details.',
      );
      return false;
    } else {
      return true;
    }
  };

  const getCurrentLocation = () => {
    let options = {
      enableHighAccuracy: false,
      timeout: 20000,
      maximumAge: 1000,
    };

    if (props.enableHighAccuracyLocation && Platform.OS === 'android') {
      options = {
        enableHighAccuracy: true,
        timeout: 20000,
      };
    }
    const getCurrentPosition =
      navigator.geolocation.getCurrentPosition ||
      navigator.geolocation.default.getCurrentPosition;

    getCurrentPosition &&
      getCurrentPosition(
        (position) => {
          if (props.nearbyPlacesAPI === 'None') {
            let currentLocation = {
              description: props.currentLocationLabel,
              geometry: {
                location: {
                  lat: position.coords.latitude,
                  lng: position.coords.longitude,
                },
              },
            };

            _disableRowLoaders();
            props.onPress(currentLocation, currentLocation);
          } else {
            _requestNearby(position.coords.latitude, position.coords.longitude);
          }
        },
        (error) => {
          _disableRowLoaders();
          console.error(error.message);
        },
        options,
      );
  };

  const _onPress = (rowData) => {
    if (rowData.isPredefinedPlace !== true && props.fetchDetails === true) {
      if (rowData.isLoading === true) {
        // already requesting
        return;
      }

      Keyboard.dismiss();

      _abortRequests();

      // display loader
      _enableRowLoader(rowData);

      // fetch details
      const request = new XMLHttpRequest();
      _requests.push(request);
      request.timeout = props.timeout;
      request.ontimeout = props.onTimeout;
      request.onreadystatechange = () => {
        if (request.readyState !== 4) return;

        if (request.status === 200) {
          const responseJSON = JSON.parse(request.responseText);

          if (responseJSON.status === 'OK') {
            // if (_isMounted === true) {
            const details = responseJSON.result;
            _disableRowLoaders();
            _onBlur();

            setStateText(_renderDescription(rowData));

            delete rowData.isLoading;
            props.onPress(rowData, details);
            // }
          } else {
            _disableRowLoaders();

            if (props.autoFillOnNotFound) {
              setStateText(_renderDescription(rowData));
              delete rowData.isLoading;
            }

            if (!props.onNotFound) {
              console.warn(
                'google places autocomplete: ' + responseJSON.status,
              );
            } else {
              props.onNotFound(responseJSON);
            }
          }
        } else {
          _disableRowLoaders();

          if (!props.onFail) {
            console.warn(
              'google places autocomplete: request could not be completed or has been aborted',
            );
          } else {
            props.onFail('request could not be completed or has been aborted');
          }
        }
      };

      request.open(
        'GET',
        `${url}/place/details/json?` +
          Qs.stringify({
            key: props.query.key,
            placeid: rowData.place_id,
            language: props.query.language,
            ...props.GooglePlacesDetailsQuery,
          }),
      );

      request.withCredentials = requestShouldUseWithCredentials();
      setRequestHeaders(request, getRequestHeaders(props.requestUrl));

      request.send();
    } else if (rowData.isCurrentLocation === true) {
      // display loader
      _enableRowLoader(rowData);

      setStateText(_renderDescription(rowData));

      delete rowData.isLoading;
      getCurrentLocation();
    } else {
      setStateText(_renderDescription(rowData));

      _onBlur();
      delete rowData.isLoading;
      let predefinedPlace = _getPredefinedPlace(rowData);

      // sending predefinedPlace as details for predefined places
      props.onPress(predefinedPlace, predefinedPlace);
    }
  };

  const _enableRowLoader = (rowData) => {
    let rows = buildRowsFromResults(_results);
    for (let i = 0; i < rows.length; i++) {
      if (
        rows[i].place_id === rowData.place_id ||
        (rows[i].isCurrentLocation === true &&
          rowData.isCurrentLocation === true)
      ) {
        rows[i].isLoading = true;
        setDataSource(rows);
        break;
      }
    }
  };

  const _disableRowLoaders = () => {
    // if (_isMounted === true) {
    for (let i = 0; i < _results.length; i++) {
      if (_results[i].isLoading === true) {
        _results[i].isLoading = false;
      }
    }

    setDataSource(buildRowsFromResults(_results));
    // }
  };

  const _getPredefinedPlace = (rowData) => {
    if (rowData.isPredefinedPlace !== true) {
      return rowData;
    }

    for (let i = 0; i < props.predefinedPlaces.length; i++) {
      if (props.predefinedPlaces[i].description === rowData.description) {
        return props.predefinedPlaces[i];
      }
    }

    return rowData;
  };

  const _filterResultsByTypes = (unfilteredResults, types) => {
    if (types.length === 0) return unfilteredResults;

    const results = [];
    for (let i = 0; i < unfilteredResults.length; i++) {
      let found = false;

      for (let j = 0; j < types.length; j++) {
        if (unfilteredResults[i].types.indexOf(types[j]) !== -1) {
          found = true;
          break;
        }
      }

      if (found === true) {
        results.push(unfilteredResults[i]);
      }
    }
    return results;
  };

  const _requestNearby = (latitude, longitude) => {
    _abortRequests();

    if (
      latitude !== undefined &&
      longitude !== undefined &&
      latitude !== null &&
      longitude !== null
    ) {
      const request = new XMLHttpRequest();
      _requests.push(request);
      request.timeout = props.timeout;
      request.ontimeout = props.onTimeout;
      request.onreadystatechange = () => {
        if (request.readyState !== 4) {
          setListLoaderDisplayed(true);
          return;
        }

        setListLoaderDisplayed(false);
        if (request.status === 200) {
          const responseJSON = JSON.parse(request.responseText);

          _disableRowLoaders();

          if (typeof responseJSON.results !== 'undefined') {
            // if (_isMounted === true) {
            var results = [];
            if (props.nearbyPlacesAPI === 'GoogleReverseGeocoding') {
              results = _filterResultsByTypes(
                responseJSON.results,
                props.filterReverseGeocodingByTypes,
              );
            } else {
              results = responseJSON.results;
            }

            setDataSource(buildRowsFromResults(results));
            // }
          }
          if (typeof responseJSON.error_message !== 'undefined') {
            if (!props.onFail)
              console.warn(
                'google places autocomplete: ' + responseJSON.error_message,
              );
            else {
              props.onFail(responseJSON.error_message);
            }
          }
        } else {
          // console.warn("google places autocomplete: request could not be completed or has been aborted");
        }
      };

      let requestUrl = '';
      if (props.nearbyPlacesAPI === 'GoogleReverseGeocoding') {
        // your key must be allowed to use Google Maps Geocoding API
        requestUrl =
          `${url}/geocode/json?` +
          Qs.stringify({
            latlng: latitude + ',' + longitude,
            key: props.query.key,
            ...props.GoogleReverseGeocodingQuery,
          });
      } else {
        requestUrl =
          `${url}/place/nearbysearch/json?` +
          Qs.stringify({
            location: latitude + ',' + longitude,
            key: props.query.key,
            ...props.GooglePlacesSearchQuery,
          });
      }

      request.open('GET', requestUrl);

      request.withCredentials = requestShouldUseWithCredentials();
      setRequestHeaders(request, getRequestHeaders(props.requestUrl));

      request.send();
    } else {
      _results = [];
      setDataSource(buildRowsFromResults([]));
    }
  };

  const _request = (text) => {
    _abortRequests();
    if (!url) {
      return;
    }
    if (supportedPlatform() && text && text.length >= props.minLength) {
      const request = new XMLHttpRequest();
      _requests.push(request);
      request.timeout = props.timeout;
      request.ontimeout = props.onTimeout;
      request.onreadystatechange = () => {
        if (request.readyState !== 4) {
          setListLoaderDisplayed(true);
          return;
        }

        setListLoaderDisplayed(false);
        if (request.status === 200) {
          const responseJSON = JSON.parse(request.responseText);
          if (typeof responseJSON.predictions !== 'undefined') {
            // if (_isMounted === true) {
            const results =
              props.nearbyPlacesAPI === 'GoogleReverseGeocoding'
                ? _filterResultsByTypes(
                    responseJSON.predictions,
                    props.filterReverseGeocodingByTypes,
                  )
                : responseJSON.predictions;

            _results = results;
            setDataSource(buildRowsFromResults(results, text));
            // }
          }
          if (typeof responseJSON.error_message !== 'undefined') {
            if (!props.onFail)
              console.warn(
                'google places autocomplete: ' + responseJSON.error_message,
              );
            else {
              props.onFail(responseJSON.error_message);
            }
          }
        } else {
          // console.warn("google places autocomplete: request could not be completed or has been aborted");
        }
      };

      if (props.preProcess) {
        setStateText(props.preProcess(text));
      }

      request.open(
        'GET',
        `${url}/place/autocomplete/json?input=` +
          encodeURIComponent(text) +
          '&' +
          Qs.stringify(props.query),
      );

      request.withCredentials = requestShouldUseWithCredentials();
      setRequestHeaders(request, getRequestHeaders(props.requestUrl));

      request.send();
    } else {
      _results = [];
      setDataSource(buildRowsFromResults([]));
    }
  };

  // eslint-disable-next-line react-hooks/exhaustive-deps
  const debounceData = useMemo(() => debounce(_request, props.debounce), [
    props.query,
    url,
  ]);

  const _onChangeText = (text) => {
    setStateText(text);
    debounceData(text);
  };

  const _handleChangeText = (text) => {
    _onChangeText(text);

    const onChangeText = props?.textInputProps?.onChangeText;

    if (onChangeText) {
      onChangeText(text);
    }
  };

  const _getRowLoader = () => {
    return <ActivityIndicator animating={true} size='small' />;
  };

  const _renderRowData = (rowData, index) => {
    if (props.renderRow) {
      return props.renderRow(rowData, index);
    }

    return (
      <Text
        style={[
          props.suppressDefaultStyles ? {} : defaultStyles.description,
          props.styles.description,
          rowData.isPredefinedPlace
            ? props.styles.predefinedPlacesDescription
            : {},
        ]}
        numberOfLines={props.numberOfLines}
      >
        {_renderDescription(rowData)}
      </Text>
    );
  };

  const _renderDescription = (rowData) => {
    if (props.renderDescription) {
      return props.renderDescription(rowData);
    }

    return rowData.description || rowData.formatted_address || rowData.name;
  };

  const _renderLoader = (rowData) => {
    if (rowData.isLoading === true) {
      return (
        <View
          style={[
            props.suppressDefaultStyles ? {} : defaultStyles.loader,
            props.styles.loader,
          ]}
        >
          {_getRowLoader()}
        </View>
      );
    }

    return null;
  };

  const _renderRow =useCallback((rowData = {}, index) => {
    return (
        <Pressable
         key={Math.random().toString(36)}
          style={({ hovered, pressed }) => [
            props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' },
            {
              backgroundColor: pressed
                ? props.listUnderlayColor
                : hovered
                ? props.listHoverColor
                : undefined,
            },
          ]}
          onPress={() =>_onPress(rowData)}
          onBlur={_onBlur}
        >
          <View
            style={[
              props.suppressDefaultStyles ? {} : defaultStyles.row,
              props.styles.row,
              rowData.isPredefinedPlace ? props.styles.specialItemRow : {},
            ]}
          >
            {_renderLoader(rowData)}
            {_renderRowData(rowData, index)}
          </View>
        </Pressable>
    );
  },[props]);


  const _renderSeparator = (sectionID, rowID) => {
    if (rowID === dataSource.length - 1) {
      return null;
    }

    return (
      <View
        key={`${sectionID}-${rowID}`}
        style={[
          props.suppressDefaultStyles ? {} : defaultStyles.separator,
          props.styles.separator,
        ]}
      />
    );
  };

  const isNewFocusInAutocompleteResultList = ({
    relatedTarget,
    currentTarget,
  }) => {
    if (!relatedTarget) return false;

    var node = relatedTarget.parentNode;

    while (node) {
      if (node.id === 'result-list-id') return true;
      node = node.parentNode;
    }

    return false;
  };

  const _onBlur = (e) => {
    if (e && isNewFocusInAutocompleteResultList(e)) return;

    if (!props.keepResultsAfterBlur) {
      setListViewDisplayed(false);
    }
    inputRef?.current?.blur();
  };

  const _onFocus = () => setListViewDisplayed(true);

  const _renderPoweredLogo = () => {
    if (!_shouldShowPoweredLogo()) {
      return null;
    }

    return (
      <View
        style={[
          props.suppressDefaultStyles ? {} : defaultStyles.row,
          defaultStyles.poweredContainer,
          props.styles.poweredContainer,
        ]}
      >
        <Image
          style={[
            props.suppressDefaultStyles ? {} : defaultStyles.powered,
            props.styles.powered,
          ]}
          resizeMode='contain'
          source={require('./images/powered_by_google_on_white.png')}
        />
      </View>
    );
  };

  const _shouldShowPoweredLogo = () => {
    if (!props.enablePoweredByContainer || dataSource.length === 0) {
      return false;
    }

    for (let i = 0; i < dataSource.length; i++) {
      let row = dataSource[i];

      if (
        !row.hasOwnProperty('isCurrentLocation') &&
        !row.hasOwnProperty('isPredefinedPlace')
      ) {
        return true;
      }
    }

    return false;
  };

  const _renderLeftButton = () => {
    if (props.renderLeftButton) {
      return props.renderLeftButton();
    }
  };

  const _renderRightButton = () => {
    if (props.renderRightButton) {
      return props.renderRightButton();
    }
  };

  const _getFlatList =useCallback( () => {
   
    if (
      stateText !== ''  &&
      listViewDisplayed === true
    ) {
      return (
        <View  style={{zIndex:0,}} >
          {[...dataSource].slice(0,5).map((item,index)=>{
            return _renderRow(item, index)
          })}
        </View>
        
      );
    }

    return null;
  },[dataSource]);

  let {
    onFocus,
    onBlur,
    onChangeText, 
    clearButtonMode,
    InputComp,
    ...userProps
  } = props.textInputProps;
  const TextInputComp = InputComp || TextInput;

  return (
    <View
      style={[
        props.suppressDefaultStyles ? {} : defaultStyles.container,
        props.styles.container,
      ]}
      pointerEvents='box-none'
    >
      {!props.textInputHide && (
        <View
          style={[
            props.suppressDefaultStyles ? {} : defaultStyles.textInputContainer,
            props.styles.textInputContainer,
          ]}
        >
          {_renderLeftButton()}
          <TextInputComp
            ref={inputRef}
            style={[
              props.suppressDefaultStyles ? {} : defaultStyles.textInput,
              props.styles.textInput,
            ]}
            value={stateText}
            placeholder={props.placeholder}
            onFocus={
              onFocus
                ? (e) => {
                    _onFocus();
                    onFocus(e);
                  }
                : _onFocus
            }
            onBlur={
              onBlur
                ? (e) => {
                    _onBlur(e);
                    onBlur(e);
                  }
                : _onBlur
            }
            clearButtonMode={clearButtonMode || 'while-editing'}
            onChangeText={_handleChangeText}
            {...userProps}
          />
          {_renderRightButton()}
        </View>
      )}
      {props.inbetweenCompo}
      {_getFlatList()}
      {props.children}
    </View>
  );
});

GooglePlacesAutocomplete.propTypes = {
  autoFillOnNotFound: PropTypes.bool,
  currentLocation: PropTypes.bool,
  currentLocationLabel: PropTypes.string,
  debounce: PropTypes.number,
  disableScroll: PropTypes.bool,
  enableHighAccuracyLocation: PropTypes.bool,
  enablePoweredByContainer: PropTypes.bool,
  fetchDetails: PropTypes.bool,
  filterReverseGeocodingByTypes: PropTypes.array,
  GooglePlacesDetailsQuery: PropTypes.object,
  GooglePlacesSearchQuery: PropTypes.object,
  GoogleReverseGeocodingQuery: PropTypes.object,
  inbetweenCompo: PropTypes.object,
  isRowScrollable: PropTypes.bool,
  keyboardShouldPersistTaps: PropTypes.oneOf(['never', 'always', 'handled']),
  listEmptyComponent: PropTypes.element,
  listLoaderComponent: PropTypes.element,
  listHoverColor: PropTypes.string,
  listUnderlayColor: PropTypes.string,
  // Must write it this way: https://stackoverflow.com/a/54290946/7180620
  listViewDisplayed: PropTypes.oneOfType([
    PropTypes.bool,
    PropTypes.oneOf(['auto']),
  ]),
  keepResultsAfterBlur: PropTypes.bool,
  minLength: PropTypes.number,
  nearbyPlacesAPI: PropTypes.string,
  numberOfLines: PropTypes.number,
  onFail: PropTypes.func,
  onNotFound: PropTypes.func,
  onPress: PropTypes.func,
  onTimeout: PropTypes.func,
  placeholder: PropTypes.string,
  predefinedPlaces: PropTypes.array,
  predefinedPlacesAlwaysVisible: PropTypes.bool,
  preProcess: PropTypes.func,
  query: PropTypes.object,
  renderDescription: PropTypes.func,
  renderHeaderComponent: PropTypes.func,
  renderLeftButton: PropTypes.func,
  renderRightButton: PropTypes.func,
  renderRow: PropTypes.func,
  requestUrl: PropTypes.shape({
    url: PropTypes.string,
    useOnPlatform: PropTypes.oneOf(['web', 'all']),
    headers: PropTypes.objectOf(PropTypes.string),
  }),
  styles: PropTypes.object,
  suppressDefaultStyles: PropTypes.bool,
  textInputHide: PropTypes.bool,
  textInputProps: PropTypes.object,
  timeout: PropTypes.number,
};

GooglePlacesAutocomplete.defaultProps = {
  autoFillOnNotFound: false,
  currentLocation: false,
  currentLocationLabel: 'Current location',
  debounce: 0,
  disableScroll: false,
  enableHighAccuracyLocation: true,
  enablePoweredByContainer: true,
  fetchDetails: false,
  filterReverseGeocodingByTypes: [],
  GooglePlacesDetailsQuery: {},
  GooglePlacesSearchQuery: {
    rankby: 'distance',
    type: 'restaurant',
  },
  GoogleReverseGeocodingQuery: {},
  isRowScrollable: true,
  keyboardShouldPersistTaps: 'always',
  listHoverColor: '#ececec',
  listUnderlayColor: '#c8c7cc',
  listViewDisplayed: 'auto',
  keepResultsAfterBlur: false,
  minLength: 0,
  nearbyPlacesAPI: 'GooglePlacesSearch',
  numberOfLines: 1,
  onFail: () => {},
  onNotFound: () => {},
  onPress: () => {},
  onTimeout: () => console.warn('google places autocomplete: request timeout'),
  placeholder: '',
  predefinedPlaces: [],
  predefinedPlacesAlwaysVisible: false,
  query: {
    key: 'missing api key',
    language: 'en',
    types: 'geocode',
  },
  styles: {},
  suppressDefaultStyles: false,
  textInputHide: false,
  textInputProps: {},
  timeout: 20000,
};

GooglePlacesAutocomplete.displayName = 'GooglePlacesAutocomplete';

export default { GooglePlacesAutocomplete };````

@juzerdhinoj-dimiour
Copy link

@jahanzaib5244 the patch works but it affects the onPress functionality.

After some testing, I found that original code seems to work as well when you turn the keyboard off in Android emulator. Now I need to explore what is causing the conflict with the keyboard popup.

@sahilkashyap64
Copy link

have you tried adding the keyboardShouldPersistTaps="handled" in the parent component

 <ScrollView keyboardShouldPersistTaps="handled">
        <View keyboardShouldPersistTaps="handled" >
        <GooglePlacesAutocomplete 
        // your everything
        />
        </View>
        </ScrollView>

@Jheysson
Copy link

Jheysson commented Aug 5, 2024

Same issue, keyboardShouldPersistTaps="handled" doesn't work for me
EDIT: nvm, it did 🚀

<ScrollView keyboardShouldPersistTaps='handled'>
<FlatList
          keyboardShouldPersistTaps='handled'
...

@jahanzaib5244
Copy link
Author

@Jheysson You can use this Patch file code
`index 99a2a13..6640f00 100644
--- a/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
+++ b/node_modules/react-native-google-places-autocomplete/GooglePlacesAutocomplete.js
@@ -13,7 +13,6 @@ import React, {
} from 'react';
import {
ActivityIndicator,

  • FlatList,
    Image,
    Keyboard,
    Platform,
    @@ -22,8 +21,10 @@ import {
    StyleSheet,
    Text,
    TextInput,
  • TouchableOpacity,
    View,
    } from 'react-native';
    +import { FlatList } from 'react-native-gesture-handler';

const defaultStyles = {
container: {
@@ -258,6 +259,7 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
};

const _onPress = (rowData) => {

  • console.log('pressed')
    if (rowData.isPredefinedPlace !== true && props.fetchDetails === true) {
    if (rowData.isLoading === true) {
    // already requesting
    @@ -645,19 +647,11 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
    return null;
    };
  • const _renderRow = (rowData = {}, index) => {
  • const _renderRow =useCallback((rowData = {}, index) => {
  • console.log('rendered')
    return (
  •  <ScrollView
    
  •    contentContainerStyle={
    
  •      props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' }
    
  •    }
    
  •    scrollEnabled={props.isRowScrollable}
    
  •    keyboardShouldPersistTaps={props.keyboardShouldPersistTaps}
    
  •    horizontal={true}
    
  •    showsHorizontalScrollIndicator={false}
    
  •    showsVerticalScrollIndicator={false}
    
  •  >
       <Pressable
    
  •    key={Math.random().toString(36)}
         style={({ hovered, pressed }) => [
           props.isRowScrollable ? { minWidth: '100%' } : { width: '100%' },
           {
    

@@ -682,9 +676,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
{_renderRowData(rowData, index)}

  •  </ScrollView>
    
    );
  • };
  • },[props]);

const _renderSeparator = (sectionID, rowID) => {
if (rowID === dataSource.length - 1) {
@@ -785,46 +779,24 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
}
};

  • const _getFlatList = () => {
  • const keyGenerator = () => Math.random().toString(36).substr(2, 10);
  • const _getFlatList =useCallback( () => {

    if (

  •  supportedPlatform() &&
    
  •  (stateText !== '' ||
    
  •    props.predefinedPlaces.length > 0 ||
    
  •    props.currentLocation === true) &&
    
  •  stateText !== ''  &&
     listViewDisplayed === true
    
    ) {
    return (
  •    <FlatList
    
  •      nativeID='result-list-id'
    
  •      scrollEnabled={!props.disableScroll}
    
  •      style={[
    
  •        props.suppressDefaultStyles ? {} : defaultStyles.listView,
    
  •        props.styles.listView,
    
  •      ]}
    
  •      data={dataSource}
    
  •      keyExtractor={keyGenerator}
    
  •      extraData={[dataSource, props]}
    
  •      ItemSeparatorComponent={_renderSeparator}
    
  •      renderItem={({ item, index }) => _renderRow(item, index)}
    
  •      ListEmptyComponent={
    
  •        listLoaderDisplayed
    
  •          ? props.listLoaderComponent
    
  •          : stateText.length > props.minLength && props.listEmptyComponent
    
  •      }
    
  •      ListHeaderComponent={
    
  •        props.renderHeaderComponent &&
    
  •        props.renderHeaderComponent(stateText)
    
  •      }
    
  •      ListFooterComponent={_renderPoweredLogo}
    
  •      {...props}
    
  •    />
    
  •    <View  style={{zIndex:0,}} >
    
  •      {[...dataSource].slice(0,5).map((item,index)=>{
    
  •        return _renderRow(item, index)
    
  •      })}
    
  •    </View>
    
  •  );
    

    }

    return null;

  • };
  • },[dataSource]);

    let {
    onFocus,
    @@ -835,6 +807,8 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
    ...userProps
    } = props.textInputProps;
    const TextInputComp = InputComp || TextInput;

  • console.log('rendered')

  • return (
    <View
    style={[
    @@ -882,9 +856,9 @@ export const GooglePlacesAutocomplete = forwardRef((props, ref) => {
    {_renderRightButton()}

    )}

  •  {props.inbetweenCompo}
    
  •  {/* {props.inbetweenCompo} */}
     {_getFlatList()}
    
  •  {props.children}
    
  •  {/* {props.children} */}
    
    );

});`

@OFD16
Copy link

OFD16 commented Aug 9, 2024

#940 (comment)

this works for me thanks a lot @jahanzaib5244 but why there is problem still exist? Why not fixed do you know?

I think i got the problem cause of i wrap the google-places-autocomplete with modal so onPress is not working fine but if you add keepResultsAfterBlur={true} prop to autocomplete it work fine. But still there is exist problem because in my case in first press it hide the keyboard after i need to press again to work onPress function.

@gesaleh
Copy link

gesaleh commented Aug 31, 2024

@jahanzaib5244 i have the same issue working on ios but not andriod
is there a file or package patch that i can use
I'm using [email protected]
when i used the code provided i'm getting this error :
ReferenceError: Property 'debounce' doesn't exist

@Sulaiman122
Copy link

Same issue
@jahanzaib5244 I tried your solution, it work but still not consistent, only first time

@Sulaiman122
Copy link

@jahanzaib5244 i have the same issue working on ios but not andriod is there a file or package patch that i can use I'm using [email protected] when i used the code provided i'm getting this error : ReferenceError: Property 'debounce' doesn't exist

You could add
import debounce from 'lodash.debounce'

@JackJBlundell
Copy link

have you tried adding the keyboardShouldPersistTaps="handled" in the parent component

 <ScrollView keyboardShouldPersistTaps="handled">
        <View keyboardShouldPersistTaps="handled" >
        <GooglePlacesAutocomplete 
        // your everything
        />
        </View>
        </ScrollView>

Thanks, this was the simple and obvious (in retrospect) issue. All fixed!

@rybaier
Copy link

rybaier commented Nov 7, 2024

@OFD16

  • RN 0.74.5
  • Expo 51.0.38

I have the same issue with keepResultsAfterBlur having to tap away the keyboard and then select with the onPress

    <GooglePlacesAutocomplete
            placeholder="Search for an address"
            fetchDetails
            keepResultsAfterBlur // This ensures that a user can tap the dropdown on android after using a tap to dismiss the keyboard
            keyboardShouldPersistTaps="handled"
         // rest of the code
         </GooglePlacesAutocomplete>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants