FaridSafi / react-native-google-places-autocomplete

Customizable Google Places autocomplete component for iOS and Android React-Native apps
MIT License
2.01k stars 854 forks source link

If you are using React Native v0.60.0+ you must follow these instructions to enable currentLocation: git.io/Jf4AR #889

Open FezVrasta opened 1 year ago

FezVrasta commented 1 year ago

Describe the bug

Using currentLocation shows this warning that points to the #more-examples section of the readme, it's not clear what the user is supposed to do from there.

Reproduction - (required - issue will be closed without this)

Run this, I tested it on iOS:

https://snack.expo.dev/@fezvrasta/react-native-google-places-autocomplete?platform=ios

Please provide a FULLY REPRODUCIBLE example.

import * as React from 'react';
import { View, StyleSheet, TextInput } from 'react-native';
import Constants from 'expo-constants';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';

const GOOGLE_PLACES_API_KEY = ''; // never save your real api key in a snack!

const App = () => {
  return (
    <View style={styles.container}>
      <GooglePlacesAutocomplete
        placeholder="Search"
        query={{
          key: GOOGLE_PLACES_API_KEY,
          language: 'en', // language of the results
        }}
        currentLocation
        onPress={(data, details = null) => console.log(data)}
        onFail={(error) => console.error(error)}
        requestUrl={{
          url:
            'https://cors-anywhere.herokuapp.com/https://maps.googleapis.com/maps/api',
          useOnPlatform: 'web',
        }} // this in only required for use on the web. See https://git.io/JflFv more for details.
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 10,
    paddingTop: Constants.statusBarHeight + 10,
    backgroundColor: '#ecf0f1',
  },
});

export default App;

Additional context

If you are using expo please indicate here:

Add any other context about the problem here, screenshots etc

pascalito007 commented 1 year ago

same issue here. using expo

YajanaRao commented 1 year ago

I am getting the same issue using expo

YajanaRao commented 1 year ago

I am able to get the functionality working by setting the height of the parent component @pascalito007

pascalito007 commented 1 year ago

@YajanaRao can you please share your code ? Mine is:

import { SafeAreaView, StyleSheet } from "react-native";
import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";
import * as Location from "expo-location";
import { useEffect, useState } from "react";
navigator.geolocation = require("expo-location");

export default function App() {
  const [location, setLocation] = useState(null);
  const [errorMsg, setErrorMsg] = useState(null);

  useEffect(() => {
    (async () => {
      let { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== "granted") {
        setErrorMsg("Permission to access location was denied");
        return;
      }

      let location = await Location.getCurrentPositionAsync({});
      setLocation(location);
    })();
  }, []);

  let text = "Waiting..";
  if (errorMsg) {
    text = errorMsg;
  } else if (location) {
    text = JSON.stringify(location);
  }
  const homePlace = {
    description: "Home",
    geometry: { location: { lat: 48.8152937, lng: 2.4597668 } },
  };
  const workPlace = {
    description: "Work",
    geometry: { location: { lat: 48.8496818, lng: 2.2940881 } },
  };

  return (
    <SafeAreaView style={styles.container}>
      <GooglePlacesAutocomplete
        placeholder="Search"
        minLength={2} // minimum length of text to search
        autoFocus={false}
        returnKeyType={"search"} // Can be left out for default return key https://facebook.github.io/react-native/docs/textinput.html#returnkeytype
        listViewDisplayed="auto" // true/false/undefined
        currentLocation={true}
        currentLocationLabel="Current location"
        nearbyPlacesAPI="GooglePlacesSearch" // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
        predefinedPlaces={[homePlace, workPlace]}
        fetchDetails={true}
        renderDescription={(row) => row.description} // custom description render
        onPress={(data, details = null) => {
          console.log(data);
        }}
        query={{
          // available options: https://developers.google.com/places/web-service/autocomplete
          key: "GOOGLE_API_KEY",
          language: "en", // language of the results
        }}
        styles={{
          container: {
            flex: 1,
            width: "100%",
          },
          textInput: {
            backgroundColor: "#1faadb",
          },
        }}
        debounce={200}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

I am getting below when I select the Current Localtion label:

ERROR TypeError: Cannot read property 'getCurrentPosition' of undefined, js engine: hermes

Below my package.json

{
  "name": "test",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "expo": "~49.0.5",
    "expo-location": "~16.1.0",
    "expo-status-bar": "~1.6.0",
    "react": "18.2.0",
    "react-native": "0.72.3",
    "react-native-google-places-autocomplete": "^2.5.1"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },
  "private": true
}
YajanaRao commented 1 year ago

@pascalito007 Here is my code (key is missing in query):

   <View
        style={{
          margin: 12,
          backgroundColor: "transparent",
          zIndex: 10,
          height: 500,
        }}
      >
        <GooglePlacesAutocomplete
          placeholder="Search"
          fetchDetails={true}
          onPress={(data, details = null) => {
            setSelected({
              latitude: details?.geometry?.location.lat,
              longitude: details?.geometry?.location.lng,
            });
          }}
          GooglePlacesDetailsQuery={{
            fields: "geometry",
          }}
          // currentLocation={true}
          listViewDisplayed={true} // true/false/undefined
          query={{
            language: "en",
          }}
        />
      </View>
pascalito007 commented 1 year ago

@YajanaRao The issue is with currentLocation. You did not set this prop.

YajanaRao commented 1 year ago

@pascalito007 It worked with currentLocation as well image

pascalito007 commented 1 year ago

@YajanaRao can you show your code with currentLocation and currentLocationLabel props set ? When the current location label is shown in the dropdown, select that and you should see the issue normaly.

YajanaRao commented 1 year ago

@pascalito007 I had an issue with showing the component itself. By setting the height to parent component I am able to get the other functionalities working. Looks like currentLocation prop does not do anything for me

pascalito007 commented 1 year ago

@YajanaRao This is what you should see: IMG-2813

IMG-2814

MarcHbb commented 1 year ago

Same issue here

@pascalito007 It worked with currentLocation as well image

I have the same issue .. Did you managed to solve it ?

bobwohl commented 10 months ago

I have this issue. The component is fully functional (as long as you set the parent's height). However, the warning does not go away when the project is configured correctly per the documentation.

bobwohl commented 10 months ago

This was a pain and is not mentioned anywhere in the docs when adding "currentLocation" to the parameters. My console gets flooded with the warning message, the "Current Location" button does not appear and nothing anywhere explains how to solve for this other than "follow the information over here..." which does not contain any information on how to correctly configure your project to use the currentLocation part of this component.

Hopefully this helps some one save some time as it is not some thing obvious:

npm view react-native version
0.73.2 

When following the instructions on using navigator.geolocation you will get the error: Cannot find name 'navigator

To address this, I had to create/add to src/declarations.d.ts this:

// declarations.d.ts
declare global {
    interface Navigator {
      geolocation: any;
    }
  }
  export {};

Make sure the project's tsconfig.json is looking for the file in the right place, if not add this to it : "include": ["src/**/*", "declarations.d.ts"]

And then reference it in the App.tsx file like so:

import Geolocation from 'react-native-geolocation-service';

// Assign Geolocation to navigator.geolocation inside the App() level.
if (typeof navigator !== 'undefined' && !navigator.geolocation) {
  (navigator as any).geolocation = Geolocation;
}

Restart the IDE and the errors should be gone, compile the app and the "Current Location" button will now appear in the auto-complete hints display.

lucksp commented 8 months ago

Any updates on this? In summary, in Expo project, currentLocation prop will not work and following the instructions to install an alternate location library such as react-native-geolocation-service may not be possible for all users. Expo users want to use expo-location since it has the same solution in terms of accessing device location service & the lat/long of the user.

I have tried converting the expo location coords response from Location.getCurrentPositionAsync({}); and then doing reverseGeoLookup to get the location, then updating the autocomplete address, but this doesn't open the dropdown to choose:

  const [initialText, setInitialText] = useState('');
  const ref = useRef<GooglePlacesAutocompleteRef | null>(null);

  useEffect(() => {
    if (initialText) {
      ref.current?.setAddressText(initialText || '');
      setTimeout(() => ref.current?.focus(), 250);
    }
  }, [initialText]);

const { data: geoLook } = useSWR(
    `https://maps.googleapis.com/maps/api/geocode/json?latlng=${str}&key=${KEY}`,
    (url: string) => getRequest<GeoLookupResponse>({ path: url }),
    {
      onSuccess: resp => {
          setInitialText(resp);
      },
    }
  );

<GooglePlacesAutocomplete
          nearbyPlacesAPI="GoogleReverseGeocoding"
          onPress={(data, details) => {
            handleSelection(data, details);
          }}
          query={{
            key: KEY,
            location: { latitude, longitude },
            radius: 5000,
          }}
          ref={ref}
        />

Also, I am trying to pass the location and radius props to the query object because it suggests this can be done in the official docs, but I am not seeing this library behave as expected from reading the docs.