Everything worked fine when currentLocation = {false}. The trouble starts as soon as you make it = {true}. Boy oh boy, first thing you get this warning :
If you are using React Native v0.60.0+ you must follow these instructions to enable currentLocation: https://git.io/Jf4AR
Indeed, if you consult the documentation for react-native-google-places-autocomplete, it says this: "If you are targeting React Native 0.60.0+ you must install either @react-native-community/geolocation (https://github.com/react-native-community/react-native-geolocation) or react-native-geolocation-service(https://github.com/Agontuk/react-native-geolocation-service).
Please make sure you follow the installation instructions there and add navigator.geolocation = require(GEOLOCATION_PACKAGE) somewhere in you application before ."
I then tried to install those packages and added the line navigator.geolocation = require(GEOLOCATION_PACKAGE)
to my code.
The problem is that those two packages need pod installs something I can't really do in my expo app.
I then tried to replace those packages with 'expo-location' which basically does the same thing. The problem is that it does have a getCurrentPosition() function. Instead, it's called getCurrentPositionAsync() and it works slightly differently. When running the code with navigator.geolocation = require('expo-location')
, I get this error:
TypeError: Cannot read property 'getCurrentPosition' of undefined
Can someone help me out?
Here's my code:
import { CommonActions, useNavigation } from "@react-navigation/native";
import React, { useContext, useEffect, useRef, useState } from "react";
import {
Alert,
Image,
Keyboard,
Linking,
Modal,
Platform,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
useWindowDimensions,
} from "react-native";
import { Camera } from "expo-camera";
import * as MediaLibrary from "expo-media-library";
import * as ImagePicker from "expo-image-picker";
import AsyncStorage from "@react-native-async-storage/async-storage";
import BottomSheet from "@gorhom/bottom-sheet";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";
import { COLORS } from "../../assets/Colors/Colors";
import { Icon } from "@rneui/themed";
import CustomButton from "../../components/CustomButton";
import CustomInput from "../../components/CustomInput";
import SocialSignInButtons from "../../components/SocialSignInButtons";
import loginContext from "../../components/loginContext/loginContext";
navigator.geolocation = require("expo-location");
const ProfileCreationPage = ({ route }) => {
const [userBio, setUserBio] = useState("");
const [selectedPlaces, setSelectedPlaces] = useState([]);
const [hasGalleryPermission, setHasGalleryPermission] = useState(null);
const [hasCameraPermission, setHasCameraPermission] = useState(null);
const [keyboardHeight, setKeyboardHeight] = useState(0);
const [image, setImage] = useState(null);
const [isBottomSheetOpened, setIsBottomSheetOpened] = useState(false);
const { status, login, hasForegroundPermissions, userLocation, userHeading } =
useContext(loginContext);
const window = useWindowDimensions();
const navigation = useNavigation();
const textInput1 = useRef();
const bottomSheetRef = useRef();
useEffect(() => {
setTimeout(() => {
textInput1.current?.focus();
}, 0);
const keyboardDidShowListener = Keyboard.addListener(
"keyboardDidShow",
(e) => {
setKeyboardHeight(e.endCoordinates.height);
}
);
const keyboardDidHideListener = Keyboard.addListener(
"keyboardDidHide",
() => {
setKeyboardHeight(0);
}
);
return () => {
keyboardDidHideListener.remove();
keyboardDidShowListener.remove();
};
}, []);
useEffect(() => {
async function checkImage() {
try {
const Value = await AsyncStorage.getItem("@Wassupp_user");
const User = JSON.parse(Value);
const Image = User.Image;
const Bio = User.Bio;
if (Image !== undefined) {
setImage(Image);
}
if (Bio !== undefined) setUserBio(Bio);
console.log(JSON.stringify(User));
} catch (e) {
console.warn(e);
}
}
checkImage();
}, []);
const onNextPressed = async () => {
// validate user
try {
const value = await AsyncStorage.getItem("@Wassupp_user");
const User = JSON.parse(value);
User.Bio = userBio;
await AsyncStorage.setItem("@Wassupp_user", JSON.stringify(User));
} catch (e) {
console.warn(e);
}
console.log("Confirm pressed");
console.log(await AsyncStorage.getItem("@Wassupp_user"));
if (route.params)
navigation.navigate(route.params.previousScreen, {
screen: route.params.previousNestedScreen,
});
else navigation.reset({ index: 0, routes: [{ name: "Home" }] });
};
const pickImageGal = async () => {
function appSettings() {
console.warn("Open settigs pressed");
if (Platform.OS === "ios") {
Linking.openURL("app-settings:");
} else RNAndroidOpenSettings.appDetailsSettings();
}
const appSettingsALert = () => {
Alert.alert(
"Allow Wassupp to Access your Photos",
"Open your app settings to allow Wassupp to access your camera roll.",
[
{
text: "Cancel",
onPress: () => console.warn("Cancel pressed"),
},
{ text: "Open settings", onPress: appSettings },
]
);
};
const galleryPermission = await MediaLibrary.requestPermissionsAsync();
if (
galleryPermission.canAskAgain == false ||
galleryPermission.status == "denied"
) {
appSettingsALert();
}
setHasGalleryPermission(galleryPermission.status === "granted");
if (hasGalleryPermission == true) {
try {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});
console.log(result);
if (!result.canceled) {
setImage(result.assets[0].uri);
const ImageResults = { Image: result.assets[0].uri };
try {
const value = await AsyncStorage.getItem("@Wassupp_user");
const User = JSON.parse(value);
if (User.Image == undefined) {
await AsyncStorage.mergeItem(
"@Wassupp_user",
JSON.stringify(ImageResults)
);
} else {
User.Image = result.assets[0].uri;
await AsyncStorage.setItem("@Wassupp_user", JSON.stringify(User));
}
console.log(JSON.stringify(User));
} catch (e) {
console.warn(e);
}
}
} catch (error) {
console.error(error);
}
}
};
const snapBottomSheetToIndex = (number) => {
bottomSheetRef.current.snapToIndex(number);
};
const onAddLocationPressed = () => {
snapBottomSheetToIndex(0);
setIsBottomSheetOpened(true);
};
const styles = StyleSheet.create({
container: {
backgroundColor: COLORS.background_Pale,
flex: 1,
//bottom: keyboardHeight,
},
background: {
backgroundColor: COLORS.background_Pale,
flex: 1,
bottom: isBottomSheetOpened ? 0 : keyboardHeight,
},
imageSlider: {
alignContent: "center",
aspectRatio: 1 / 1,
backgroundColor: COLORS.image_Slider_Background,
borderColor: COLORS.input_Border_Violet,
borderWidth: 7.5,
justifyContent: "center",
width: "100%",
},
title: {
color: COLORS.background,
fontSize: 20,
fontWeight: "bold",
marginTop: 20,
marginLeft: 20,
},
});
return (
<GestureHandlerRootView style={{ flex: 1, backgroundColor: "black" }}>
<ScrollView style={styles.container}>
<View style={styles.background}>
<Pressable
style={[
styles.imageSlider,
image === null ? {} : { borderWidth: 0 },
]}
onPress={pickImageGal}
>
{image == null ? (
<View>
<Icon
name="images"
type="font-awesome-5"
color={COLORS.background}
size={40}
/>
<Text
style={{
textAlign: "center",
color: COLORS.background,
fontSize: 16,
fontWeight: "bold",
}}
>
Add images to your profile
</Text>
</View>
) : (
<View style={{ flex: 1 }}>
<Image source={{ uri: image }} style={{ flex: 1 }} />
</View>
)}
</Pressable>
<Text style={styles.title}>About me</Text>
<CustomInput
ref={textInput1}
multiline={true}
textAlign={"justify"}
maxLength={500}
style={{ marginLeft: 10, width: window.width * 1.184 }}
value={userBio}
onChangeText={(textValue) => {
setUserBio(textValue);
}}
/>
<Text style={styles.title}>Places to take me on a date</Text>
<CustomButton
text="Add location"
onPress={() => {
onAddLocationPressed();
}}
style={{ alignSelf: "center", marginTop: 15 }}
type={selectedPlaces.length == 1 ? "SECONDARY" : "SECONDARY2"}
image={require("/Users/aurelie/Wassupp/app/assets/AppIcon/App_Icon.png")}
/>
<CustomButton
onPress={() => {
onNextPressed(route);
}}
style={{ alignSelf: "center", marginTop: 30, width: "30%" }}
text="Confirm"
type="PRIMARY_SOCIAL_MEDIA"
/>
</View>
</ScrollView>
<BottomSheet
index={-1}
ref={bottomSheetRef}
onClose={() => {
setIsBottomSheetOpened(false);
}}
snapPoints={[keyboardHeight != 0 ? 200 + keyboardHeight : 200]}
enablePanDownToClose={true}
>
<View style={{ flex: 1 }}>
<GooglePlacesAutocomplete
placeholder="Search"
currentLocation={true}
minLength={2}
debounce={200}
nearbyPlacesAPI="GooglePlacesSearch"
onPress={(data, details = null) => {
// 'details' is provided when fetchDetails = true
console.log(data, details);
}}
query={{
key: "YOUR GOOGLE API KEY",
language: "en",
}}
/>
</View>
</BottomSheet>
</GestureHandlerRootView>
);
};
export default ProfileCreationPage;
Please save me!
Try it like this: