Search code examples
arraysstringreact-nativecity

City location in expo location react-native


I'm trying to extract only the city location using expo-location. I was able to get the full location of the user using this code:

1    import React, { useState, useEffect } from 'react';
2    import { Text, View, StyleSheet } from 'react-native';
3    import * as Location from 'expo-location';
4    
5    export default function App() {
6      const [location, setLocation] = useState(null);
7      const [errorMsg, setErrorMsg] = useState(null);
8    
9      useEffect(() => {
10       (async () => {
11          let { status } = await Location.requestPermissionsAsync();
12          if (status !== 'granted') {
13            setErrorMsg('Permission to access location was denied');
14          }
15    
16          let regionName = await Location.reverseGeocodeAsync( { longitude: 37.6172999, latitude: 55.755826 } );
17          setLocation(regionName);
18          console.log(regionName);
19       })();
20      }, []);
21    
22      let text = 'Waiting..';
23      if (errorMsg) {
24        text = errorMsg;
25      } else if (location) {
26        text = JSON.stringify(location);
27      }
28    
29      return (
30        <View style={styles.container}>
31          <Text>{text}</Text>
32        </View>
33      );
34    }
35    
36    const styles = StyleSheet.create({
37      container: {
38        flex: 1,
39        backgroundColor: '#bcbcbc',
40        alignItems: 'center',
41        justifyContent: 'center',
42      },
43      big: {
44        fontSize: 18,
45        color: "white",
46      }
47    });
48

So i've tried to get only the city location by changing the line 26 to text = JSON.stringify([0].city); but nothing is being showed on my phone anymore...

The terminal shows me this log from console.log:

Array [
  Object {
    "city": "Moscow",
    "country": "Russia",
    "district": "Central Administrative Okrug",
    "isoCountryCode": "RU",
    "name": "109012",
    "postalCode": "109012",
    "region": null,
    "street": null,
    "subregion": "Moscow",
    "timezone": null,
  },
]

If someone can help me find a way to get the city location I'd be very glad

I thought it could help me if I tried to get the city like this, CHANGING FROM LINE 22 TO LINE 27 TO THIS:

const city = "Waiting..."
if (errorMsg) {
city = errorMsg;
} else if (location) {
city = Object.keys(regionName).reduce((result, key) => {
  return result.concat(regionName[key].city)
}, []);
};

to get only the array [0], but for some reason the only thing I got was it: [Unhandled promise rejection: Error: "city" is read-only] Why read-only? I didn't get it... can somebody help me here?


Solution

  • Screenshot:

    Screenshot

    Here is the working example:

    import React, { useEffect, useState } from 'react';
    import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
    import Constants from 'expo-constants';
    
    // You can import from local files
    import AssetExample from './components/AssetExample';
    
    let apiKey = 'YOUR_API_KEY';
    
    // or any pure javascript modules available in npm
    import { Card } from 'react-native-paper';
    import * as Location from 'expo-location';
    
    export default function App() {
      const [location, setLocation] = useState(null);
      const [errorMsg, setErrorMsg] = useState(null);
      const [getLocation, setGetLocation] = useState(false);
    
      useEffect(() => {
        (async () => {
          let { status } = await Location.requestPermissionsAsync();
          if (status !== 'granted') {
            setErrorMsg('Permission to access location was denied');
          }
    
          Location.setGoogleApiKey(apiKey);
    
          console.log(status);
    
          let regionName = await Location.reverseGeocodeAsync({
            latitude: 19.2514799,
            longitude: 75.7138884,
          });
    
          setLocation(regionName);
          console.log(regionName, 'nothing');
    
          // console.log();
        })();
      }, [getLocation]);
    
    
      return (
        <View style={styles.container}>
          <Text style={styles.big}>
            {!location ? 'Waiting' : JSON.stringify(location[0]["city"])}
          </Text>
          <TouchableOpacity onPress={() => setGetLocation(!getLocation)}>
            <View
              style={{
                height: 100,
                backgroundColor: 'teal',
                justifyContent: 'center',
                alignItems: 'center',
                borderRadius: 10,
                marginTop: 20,
              }}>
              <Text style={styles.btnText}> GET LOCATION </Text>
            </View>
          </TouchableOpacity>
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: 'white',
        alignItems: 'center',
        justifyContent: 'center',
      },
      big: {
        fontSize: 18,
        color: 'black',
        fontWeight: "bold"
      },
      btnText:{
        fontWeight: "bold",
        fontSize: 25,
        color: "white"
      }
    });
    

    Live Demo: Expo Snack