我有时可以获得正确的位置,大多数情况下在状态更新之前,render()会调用提取无效状态。
我试过添加async + await条件但无济于事。一旦将位置数据设置为状态,我如何确保渲染地图。
这是代码。
所以再次,可能是我可以在某处放置nexttick()左右以确保更新状态用于渲染?
import React, { Component } from "react";
import {Platform,Text,Image,View,StyleSheet,Dimensions} from "react-native";
import { MapView, Constants, Location, Permissions } from "expo";
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;
export default class ComplaintScreen extends Component {
state = {
location: null,
errorMessage: null,
positionState: {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0
},
markerPosition: {
latitude: 0,
longitude: 0
}
};
async componentWillMount() {
if (Platform.OS === "android" && !Constants.isDevice) {
this.setState({
errorMessage:
"Oops, this will not work on Sketch in an Android emulator. Try it on your device!"
});
} else {
await this._getLocationAsync();
}
}
_getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
this.setState({
errorMessage: "Permission to access location was denied"
});
}
let location = await Location.getCurrentPositionAsync(
{
enableHighAccuracy: true, timeout:5000, maxiumumAge: 10000
});
this.setState({ location });
var lat = parseFloat(location.coords.latitude);
var long = parseFloat(location.coords.longitude);
var region = {
latitude: lat,
longitude: long,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA
};
this.setState({ positionState: region });
this.setState({ markerPosition: region });
};
render() {
return (
console.log(this.state.positionState),
<View style={Styles.container}>
<MapView style={Styles.map} initialRegion={this.state.positionState}>
<MapView.Marker coordinate={this.state.markerPosition}>
<View style={Styles.radius}>
<View style={Styles.marker} />
</View>
</MapView.Marker>
</MapView>
</View>
);
}
}
const Styles = StyleSheet.create({
{some styles were here removed to keep the post short}
});
答案 0 :(得分:1)
作为替代方案,您可能还希望通过使用MapView的引用来调用react-maps-native animateToRegion。
这是我建议的替代方案,适用于我的项目:
_getLocationAsync = async()=> {
let {status} = await Permissions.askAsync(Permissions.LOCATION);
if(status!=='granted'){
this.setState({errorMessage:"Permissions not granted."})
}
let location = await Location.getCurrentPositionAsync({});
this.map.animateToRegion({
latitude: location.coords.latitude,
longitude: location.coords.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}, 200)}
在此处查看参考: MapView API
答案 1 :(得分:0)
我做了一些事情,比如添加一个活动加载器然后检查coords是否已更新,然后才显示地图。现在有效,如果有更好的方法,就会喜欢它。
import React, { Component } from "react";
import {
Platform,
Text,
Image,
View,
StyleSheet,
Dimensions,
ActivityIndicator,
} from "react-native";
import { MapView, Constants, Location, Permissions } from "expo";
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;
export default class ComplaintScreen extends Component {
static navigationOptions = {
title: "New Complaint",
headerStyle: {
backgroundColor: "#010245",
paddingTop: Constants.statusBarHeight,
height: 60 + Constants.statusBarHeight
},
headerTintColor: "#fff",
headerRight: (
<Image
source={require("../assets/img/header/hr.png")}
style={{ justifyContent: "center", padding: 3, margin: 3 }}
/>
)
};
state = {
location: null,
errorMessage: null,
loading: true,
loadingMap:false,
positionState: {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0
},
markerPosition: {
latitude: 0,
longitude: 0
}
};
async componentWillMount() {
Location.setApiKey('AIzaSyAHSZHScQK-AslKB8QSIyDfqwGc2adFaUM');
if (Platform.OS === "android" && !Constants.isDevice) {
this.setState({
errorMessage:
"Oops, this will not work on Sketch in an Android emulator. Try it on your device!"
});
} else {
await this._getLocationAsync();
}
}
_getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
this.setState({
errorMessage: "Permission to access location was denied"
});
}
let location = await Location.getCurrentPositionAsync(
{
enableHighAccuracy: true, timeout:5000, maxiumumAge: 10000
});
this.setState({ location });
var lat = parseFloat(location.coords.latitude);
var long = parseFloat(location.coords.longitude);
var region = {
latitude: lat,
longitude: long,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA
};
this.setState({ positionState: region });
this.setState({ markerPosition: region });
};
componentDidUpdate(){
if (this.state.positionState.latitude!=='0'){
this.state.loadingMap = true;
this.state.loading = false;
}
}
render() {
return (
console.log(this.state.positionState),
<View style={Styles.container}>
{this.state.loadingMap &&
<MapView style={Styles.map} initialRegion={this.state.positionState}>
<MapView.Marker coordinate={this.state.markerPosition}>
<View style={Styles.radius}>
<View style={Styles.marker} />
</View>
</MapView.Marker>
</MapView>
}
{this.state.loading &&
<View style={Styles.loading}>
<ActivityIndicator size='large' />
</View>
}
</View>
);
}
}
const Styles = StyleSheet.create({
radius: {
height: 50,
width: 50,
borderRadius: 50 / 2,
overflow: "hidden",
backgroundColor: "rgba(0, 122, 255, 0.1)",
borderWidth: 1,
borderColor: "rgba(0, 112, 255, 0.3)",
alignItems: "center",
justifyContent: "center"
},
marker: {
height: 20,
width: 20,
borderWidth: 3,
borderColor: "white",
borderRadius: 20 / 2,
overflow: "hidden",
backgroundColor: "#007AFF"
},
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
},
map: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: "absolute"
},
loading: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'
}
});
&#13;