Quantcast
Channel: Active questions tagged react-native+ios - Stack Overflow
Viewing all articles
Browse latest Browse all 16552

React-native-maps and Geolocation not getting location properly

$
0
0

I am very new to learning React Native and would appreciate any help that can be provided with my code. I am currently working off of tutorials and have been stuck for hours. Hopefully this is enough info to get some help. Thanks in advance!

My goal

I am trying to do three things (in this order):

  1. Get the user's current location
  2. Fetch the items data from an API (example outlined below). It should be noted that eventually the contents of the fetch will be dependent on the user's current location.
  3. Parse the items data to create markers and a unique list of categories and place those on the map with the user's current location at center to begin with.

I am looking to be able to watch the user's location and move and update the map accordingly. I also don't want to show the map until all of the markers are in place.

Here are my react versions: react-native-cli: 2.0.1 react-native: 0.63.2

My Bugs

I am using both the Android Studio emulator as well as the Xcode emulator and am currently running into the following problems:

  1. The iOS emulator on Xcode renders fine the first time, but on subsequent refreshes I see 1 or two of my 5 markers missing.
  2. On Android, the map loads perfectly then appears to immediately redraw itself and center on the Googleplex in California instead of the user's current location.Emulator location is set to London, UK

I suspect I might have some race condition with fetching the items and current location before the map renders but I can't be sure.

My Code

//my API response structure

{"id": "96845","title": "Item_title_goes_here","image": "https://someURL/image.JPG","stories": 46,"lat": some_lat_number,"lon": some_lon_number,"category": "category_name","description": "long_description"},
//ajax.js export default {    async fetchInitialItems() {        try {            const response = await fetch(apiHost +'/api/v1/items/');            const responseJson = await response.json();            return responseJson;        } catch (error) {            console.error(error);        }    },    async fetchItemDetail(itemId) {        try {            const response = await fetch(apiHost +'/api/items/'+ itemId);            const responseJson = await response.json();            return responseJson;        } catch (error) {            console.error(error);        }    },};
//ExploreScreen.js (my map component)import React, { Component } from 'react';import {    View,    Text,    StyleSheet,    Image,    Animated,    Dimensions,    TouchableOpacity,    PermissionsAndroid,    ScrollView,    Platform,    StatusBar,} from 'react-native';import MapView, {    PROVIDER_GOOGLE,    Marker,    Callout,    Polygon,} from 'react-native-maps';import PropTypes from 'prop-types';import Geolocation from '@react-native-community/geolocation';import { mapDarkStyle, mapStandardStyle } from '../model/mapData';import ajax from '../utils/ajax';import MapCarousel from './MapCarousel';import Ionicons from 'react-native-vector-icons/Ionicons';import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';import Fontisto from 'react-native-vector-icons/Fontisto';import StarRating from '../components/StarRating';/**|--------------------------------------------------| Variables|--------------------------------------------------*/const { width, height } = Dimensions.get('window');const SCREEN_HEIGHT = height;const SCREEN_WIDTH = width;const ASPECT_RATIO = width / height;const LATITUDE_DELTA = 0.0422;const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO;const darkTheme = false;/**|--------------------------------------------------| Component|--------------------------------------------------*/class ExploreScreen extends React.Component {    /****** Props & States ******/    state = {        region: {            latitude: 0,            longitude: 0,            latitudeDelta: LATITUDE_DELTA,            longitudeDelta: LONGITUDE_DELTA,        },        items: [],        markers: [],        categories: [],        currentMapRegion: null,    };    /****** Functions ******/    ///when carousel item selected    onCarouselItemSelected() {        alert('carousel item selected');    }    //when the carousel in scrolled    onCarouselIndexChange(itemID) {        const item = this.state.items.find(item => item.id == itemID);        const marker = this.state.markers.find(marker => marker.id == itemID);        const coordinates = { lat: item.lat, lon: item.lon };        this.goToLocation(coordinates);    }    //get current position    getLocation(that) {        Geolocation.getCurrentPosition(            //get the current location            position => {                const region = {                    latitude: parseFloat(position.coords.latitude),                    longitude: parseFloat(position.coords.longitude),                    latitudeDelta: LATITUDE_DELTA,                    longitudeDelta: LONGITUDE_DELTA,                };                that.setState({ region });            },            error => alert(error.message),            { enableHighAccuracy: true, timeout: 20000 },        );        //get location on location change        that.watchID = Geolocation.watchPosition(position => {            const currentRegion = {                latitude: position.coords.latitude,                longitude: position.coords.longitude,                latitudeDelta: LATITUDE_DELTA,                longitudeDelta: LONGITUDE_DELTA,            };            this.setState({ region: currentRegion });        });    }    //move map to a lat/lon    goToLocation(coordinates) {        if (this.map) {            this.map.animateToRegion({                latitude: coordinates.lat,                longitude: coordinates.lon,                latitudeDelta: LATITUDE_DELTA,                longitudeDelta: LONGITUDE_DELTA,            });        }    }    //when the region changes for the map    onRegionChangeComplete(region) {        //I dont know what to do here     }    //move map to center of current location    gotToCenter() {        if (this.map) {            this.map.animateToRegion({                latitude: this.state.region.latitude,                longitude: this.state.region.longitude,                latitudeDelta: LATITUDE_DELTA,                longitudeDelta: LONGITUDE_DELTA,            });        }    }    //map the categories store in the state    mapCategories = () => {        const uniqueCategories = [];        this.state.items.map(item => {            if (uniqueCategories.indexOf(item.category) === -1) {                uniqueCategories.push(item.category);            }        });        this.setState({ categories: uniqueCategories });    };    //map the items to markers and store in the state    mapMarkers = () => {        const markers = this.state.items.map(item => (<Marker                key={item.id}                coordinate={{ latitude: item.lat, longitude: item.lon }}                image={require('../assets/map_marker.png')}                tracksViewChanges={false}                title={item.title}                description={item.description}            />        ));        this.setState({ markers: markers });    };    /****** Lifecycle Functions ******/    async componentDidMount() {        var that = this;        //Checking for the permission just after component loaded        if (Platform.OS === 'ios') {            //for ios            this.getLocation(that);        } else {            //for android            async function requestLocationPermission() {                try {                    const granted = await PermissionsAndroid.request(                        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,                        {                            title: 'Location Access Required',                            message: 'This App needs to Access your location',                        },                    );                    if (granted === PermissionsAndroid.RESULTS.GRANTED) {                        //To Check, If Permission is granted                        that.getLocation(that);                    } else {                        alert('Permission Denied');                    }                } catch (err) {                    alert('err', err);                    console.warn(err);                }            }            requestLocationPermission();        }        //get location on location change        that.watchID = Geolocation.watchPosition(position => {            const currentRegion = {                latitude: parseFloat(position.coords.latitude),                longitude: parseFloat(position.coords.longitude),                latitudeDelta: LATITUDE_DELTA,                longitudeDelta: LONGITUDE_DELTA,            };            this.setState({ region: currentRegion });        });        console.log(this.state.region);        const items = await ajax.fetchInitialItems();        this.setState({ items });        this.mapMarkers();        this.mapCategories();    }    componentWillUnmount = () => {        Geolocation.clearWatch(this.watchID);    };    render() {        const lat = this.state.region.latitude;        const lon = this.state.region.longitude;        if (this.state.items && lat && lon) {            return (<View><MapView                        ref={map => {                            this.map = map;                        }}                        onRegionChangeComplete={this.onRegionChangeComplete.bind(this)}                        toolbarEnabled={false}                        showsMyLocationButton={false}                        provider={PROVIDER_GOOGLE}                        style={styles.map}                        customMapStyle={darkTheme ? mapDarkStyle : mapStandardStyle}                        showsUserLocation={true}                        followsUserLocation={true}                        region={this.state.region}>                        {this.state.markers}</MapView>                    {/* center button */}<TouchableOpacity                        onPress={this.gotToCenter.bind(this)}                        style={styles.centerButtonContainer}><Ionicons name="md-locate" size={20} /></TouchableOpacity><View style={styles.carousel}><MapCarousel                            data={this.state.items}                            onPressItem={() => {                                this.onCarouselItemSelected.bind(this);                            }}                            onUpdateLocation={this.onCarouselIndexChange.bind(this)}                        /></View></View>            );        } else {            return (<View style={styles.container}><Text style={styles.header}>Loading...</Text></View>            );        }    }}/**|--------------------------------------------------| Styles|--------------------------------------------------*/const styles = StyleSheet.create({    container: {        ...StyleSheet.absoluteFillObject,        height: '100%',        width: '100%',        justifyContent: 'center',        alignItems: 'center',    },    map: {        height: '100%',    },    carousel: {        position: 'absolute',        bottom: 25,    },    header: {        fontSize: 50,    },    //character name    name: {        fontSize: 15,        marginBottom: 5,    },    //character image    image: {        width: 170,        height: 80,    },    //center button    centerButtonContainer: {        width: 40,        height: 40,        position: 'absolute',        bottom: 260,        right: 10,        borderColor: '#191919',        borderWidth: 0,        borderRadius: 30,        backgroundColor: '#d2d2d2',        justifyContent: 'center',        alignItems: 'center',        shadowColor: '#000',        shadowOffset: {            width: 0,            height: 9,        },        shadowOpacity: 0.48,        shadowRadius: 11.95,        elevation: 18,        opacity: 0.9,    },});export default ExploreScreen;

Viewing all articles
Browse latest Browse all 16552

Trending Articles