Я пытаюсь получить местоположение пользователя в своем приложении React Native и переместить мой MapView в это местоположение. Когда приложение загружается, оно показывает местоположение (по умолчанию, а не из-за моего действия), но когда действие выполняется, я получаю эту ошибку:
Exception thrown while executing UI block:
Invalid Region <center:+37.33233141, -122.03121860 span: +0.00044916, -0.05737702>
Объект региона, передаваемый моему MapView (из действий с моим местоположением), равен
{
latitude: 37.33233141,
longitude: -122.0312186,
accuracy: 0.05,
latitudeDelta: 0.0004491555874955085,
longitudeDelta: -0.05737702242408729
};
Я на самом деле скопировал код из старого проекта, у которого была такая же проблема, а затем в какой-то момент перестал иметь проблему.
В любом случае, вот мой код:
MapScreen.js
import React, { Component } from "react";
import MapView, { Marker, Callout } from "react-native-maps";
import { connect } from "react-redux";
import { View, Button, Text, Platform, TextInput } from "react-native";
const CurrentRegionMarker = ({ currentRegion }) => {
return currentRegion && currentRegion.showMarker ? (
<Marker coordinate={currentRegion} pinColor={"green"} />
) : null;
};
class MapScreen extends Component {
state = { region: null };
render() {
return (
<View style={styles.container}>
<MapView
style={{ flex: 1 }}
showsUserLocation={true}
region={this.props.currentRegion}
>
<CurrentRegionMarker currentRegion={this.props.currentRegion} />
</MapView>
</View>
);
}
}
export default connect(({ location }) => ({
currentRegion: location.currentRegion
}))(MapScreen);
locationActions.js
// @flow
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import type {
Location as LocationType,
LocationAction
} from "../reducers/locationReducer";
import type { Saga } from "redux-saga";
import { call, put, select, takeEvery, all } from "redux-saga/effects";
export function getLocationAsync(): LocationAction {
return { type: "USER_LOCATION_START" };
}
export function* getLocationSaga(): Saga<void> {
try {
const region = yield call(getUserLocation);
yield put({ type: "USER_LOCATION_SUCCESS", region });
} catch (error) {
yield put({ type: "USER_LOCATION_FAILURE", error: error.message });
}
}
async function getUserLocation(): LocationType {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
return console.warn("Permission to access location was denied");
}
let location = await Location.getCurrentPositionAsync({});
let { latitude, longitude } = location.coords;
let accuracy = 0.05;
let region = { latitude, longitude, accuracy };
console.log("direct", calculateRegion(region));
console.log("interpolated", { ...region, ...calculateRegion(region) });
return { ...calculateRegion(region), accuracy };
}
function calculateRegion({
latitude,
longitude,
accuracy = 0.05
}): LocationType {
const oneDegreeOfLongitudeInMeters = 111.32;
const circumference = 40075 / 360;
const latitudeDelta = accuracy / oneDegreeOfLongitudeInMeters;
const longitudeDelta = accuracy * (1 / Math.cos(latitude * circumference));
const region = { latitude, longitude, latitudeDelta, longitudeDelta };
return region;
}
export default function* locationSaga(): Saga<void> {
yield all([yield takeEvery("USER_LOCATION_START", getLocationSaga)]);
}
locationReducer.js
// @flow
const initialState: LocationState = {
currentRegion: {
latitude: 0,
longitude: 0,
latitudeDelta: 0.00922,
longitudeDelta: 0.00421,
showMarker: false
}
};
export default function dealsReducer(
state: LocationState = initialState,
action: LocationAction
): LocationState {
switch (action.type) {
case "USER_LOCATION_SUCCESS":
return { ...state, currentRegion: action.region };
case "USER_LOCATION_FAILURE":
return { ...state, error: action.error };
default:
return state;
}
}
export type Location = {
latitude: number,
longitude: number,
latitudeDelta: number,
longitudeDelta: number,
showMarker?: boolean
};
type LocationState = {
+currentRegion: Location,
+error: ?string
};
export type LocationAction =
| { type: "USER_LOCATION_START" }
| {
type: "USER_LOCATION_SUCCESS",
region: Location
}
| {
type: "USER_LOCATION_FAILURE",
error: string
};
Обновление: Похоже, что значения longitudeDelta
и latitudeDelta
были проблемой. Сейчас я использую для них жестко запрограммированные значения, но я до сих пор не уверен, почему этот код работает как в одном приложении, а не в другом.