【问题标题】:react-native: setState() not updating MapView initialRegion with react-native-geolocation-servicereact-native: setState() 不使用 react-native-geolocation-service 更新 MapView initialRegion
【发布时间】:2019-12-05 10:17:03
【问题描述】:

在我的 react-native 应用程序中,我是 react-native-geolocation-service 来获取用户位置并将其显示在 MapView 上。下面是我从网上提供的各种示例中尝试的一个简单代码。

import React, { Component } from 'react'
import 
{
    View,
    StyleSheet,
    Dimensions
} from 'react-native'
import MapView, { PROVIDER_GOOGLE, Marker } from 'react-native-maps';

//import Geolocation from '@react-native-community/geolocation';
import Geolocation from 'react-native-geolocation-service';
import {hasLocationPermission} from '../../../services/Helper'

const {width, height} = Dimensions.get('window')

const SCREEN_HEIGHT = height
const SCREEN_WIDTH = width
const ASPECT_RATIO = width / height
const LATITUDE_DELTA = 0.0922
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO
const MAP_LOCATION_OPTIONS = { enableHighAccuracy: true, timeout: 20000};

class NearMeTest extends Component {

    constructor(){
        super()
        this.state = {
            initialPosition: {
                latitude: 0,
                longitude: 0,
                latitudeDelta: 0,
                longitudeDelta: 0,
            },
            markers: [{
                title: 'shop1',
                coordinates: {
                  latitude: 12.9782933,
                  longitude: 77.68838
                },
              },
              {
                title: 'shop2',
                coordinates: {
                  latitude: 12.9613824,
                  longitude: 77.7109504
                },
              },
            ]
        }
        this.onCurrentLocationSuccess = this.onCurrentLocationSuccess.bind(this)
        this.onCurrentLocationError = this.onCurrentLocationError.bind(this)
    }

    onCurrentLocationSuccess(pos) {

      var crd = pos.coords;
      var lat = parseFloat(crd.latitude)
      var long = parseFloat(crd.longitude)
      console.log('Your current position is:');
      console.log(`Latitude : ${lat}`);
      console.log(`Longitude: ${long}`);
      console.log(`More or less ${crd.accuracy} meters.`);
      var initialRegion = {
        latitude: lat,
        longitude: long,
        latitudeDelta: LATITUDE_DELTA,
        longitudeDelta: LONGITUDE_DELTA,
      }
      this.setState({initialPosition: initialRegion})
      };

    onCurrentLocationError(err) {
      console.warn(`ERROR(${err.code}): ${err.message}`);
      alert(err.message)
    };

    componentDidMount(){
      if(hasLocationPermission()){
        console.log('Location Permission present, getting current location')
        Geolocation.getCurrentPosition(this.onCurrentLocationSuccess,this.onCurrentLocationError,MAP_LOCATION_OPTIONS)
      }
    }


    render() {
        console.log(this.state.initialPosition)
        return (
            <View style={styles.container}>
                <MapView
                provider={PROVIDER_GOOGLE} // remove if not using Google Maps
                style={styles.map}
                initialRegion={this.state.initialPosition}
                >
                    <Marker
                        coordinate = {{
                            latitude: this.state.initialPosition.latitude,
                            longitude: this.state.initialPosition.longitude, 
                        }}
                    >
                    </Marker>
                    {this.state.markers.map((marker, i) => (
                    <Marker
                        key={i}
                        coordinate={marker.coordinates}
                        title={marker.title}
                    >
                    </Marker>
                    ))}
                </MapView>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
      ...StyleSheet.absoluteFillObject,
      height: SCREEN_HEIGHT,
      width: SCREEN_WIDTH,
      justifyContent: 'flex-end',
      alignItems: 'center',
    },
    map: {
      ...StyleSheet.absoluteFillObject,
    },
   });

export default NearMeTest

我在componentDidMount() 中获取位置,但是当我调用setState() 来设置我的initialPosition 时,我没有看到它在MapView 中更新。

另外,另一个有趣的事情是,如果我使用来自@react-native-community/geolocation 的地理编码器,那么它会按预期工作。

我有定位权限,我正在使用 Android Marshmellow 设备进行测试。

【问题讨论】:

  • 那么为什么要使用 react-native-geolocation-service,如果 @react-native-community/geolocation 做你想做的事
  • @DevAS 因为 react-native-geolocation-servce 在 android 中使用 FusedLocationProvider 可以提供更准确的结果。此外,对于一些最新的手机,react-native-community/geolocation 会超时。

标签: javascript android react-native geolocation


【解决方案1】:

如果唯一目的是在地图上显示用户的位置,我建议如下:

<MapView
  style={styles.map}
  region={this.state.region}
  onRegionChangeComplete={this.onRegionChange}
  onUserLocationChange={this.onUserLocationChange}
  showsUserLocation={true}>

如果您对showUserLocation={true} 有任何问题,请参阅此https://github.com/react-native-community/react-native-maps/issues/2747#issuecomment-475662120

链接中的线程只是建议在准备好地图时请求许可。以下是来自上述链接的sn-p。

<Map
  onMapReady={() => {
     PermissionsAndroid.request(
     PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
  ).then(granted => {
     alert(granted) // just to ensure that permissions were granted
 });
}}/>

【讨论】:

    【解决方案2】:

    您看不到更新,因为您正在更新 initialPosition。如果您将 initialRegion 设置为 region 属性,它将起作用。

    【讨论】:

    • 你确定你理解你所读的吗?我说您正在使用 initialPosition 状态更新 initialRegion。但 initialRegion 是唯一的,无法更新。您必须设置 region={this.state.initialPosition}。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    相关资源
    最近更新 更多