I am trying to implement to search and pinpoint a location in react native. I am using react-native-maps
and react-native-google-places-autocomplete
packages for their obvious usages.
First I have initiated region in the state as:
constructor(){
this.state={
mapRegion: {
latitude: this.props.latitude ? this.props.latitude : 27.7172,
longitude: this.props.longitude ? this.props.longitude : 85.3240,
latitudeDelta: 0.005,
longitudeDelta: 0.005,
},
}
}
I have tried to update the region on pressing the autocompleted search results as well as upon marker drag. But I get an error as:
Error: You attempted to set the key latitude with the value '27' on an object that is meant to be immutable and has been frozen.
I have implemented the code as:
<GooglePlacesAutocomplete
placeholder='Search'
fetchDetails={true}
onPress={(data, details = null) => {
let tempMapRegion = this.state.mapRegion;
tempMapRegion.latitude = details.geometry.location.lat;
tempMapRegion.longitude = details.geometry.location.lng;
this.setState({ mapRegion: tempMapRegion })
}}
query={{
key: AppSettings.googleMapApiKey,
language: 'en',
}}
/>
<MapView
initialRegion={{
latitude: this.props.latitude ? this.props.latitude : 27.7172,
longitude: this.props.longitude ? this.props.longitude : 85.3240,
latitudeDelta: 0.005,
longitudeDelta: 0.005,
}}
region={this.state.mapRegion}
onRegionChange={(e) => { this.onRegionChange(e) }}
style={{ height: 300, width: 300 }}
>
<Marker draggable
coordinate={this.state.mapRegion}
onDragEnd={(e) => {
let tempMapRegion = this.state.mapRegion;
tempMapRegion.latitude = e.nativeEvent.coordinate.latitude
tempMapRegion.longitude = e.nativeEvent.coordinate.longitude
this.setState({ mapRegion: tempMapRegion })
}}
/>
</MapView>
The onRegionChange
in the MapView
works smoothly and marker is dragged automatically to the centre, but the reverse process brings up the above error.
What is causing this error and how do I get past this?
<View style={{ padding: 2, }}>
<GooglePlacesAutocomplete
placeholder='Search'
fetchDetails={true}
onPress={(data, details = null) => {
let tempMapRegion = this.state.mapRegion;
tempMapRegion.latitude = details.geometry.location.lat;
tempMapRegion.longitude = details.geometry.location.lng;
this.map.animateToRegion(this.newRegion(tempMapRegion));
this.setState({ address: data.description })
}}
query={{
key: AppSettings.googleMapApiKey,
language: 'en',
}}
/>
</View>
<MapView
provider={this.props.provider}
ref={ref => { this.map = ref; }}
mapType={MAP_TYPES.TERRAIN}
initialRegion={this.state.mapRegion}
onRegionChangeComplete={(e) => { this.onRegionChange(e) }}
style={{ height: width, width: width, marginTop: -5 }}
>
<Marker draggable
coordinate={this.state.mapRegion}
onDragEnd={(e) => {
let tempMapRegion = this.state.mapRegion;
tempMapRegion.latitude = e.nativeEvent.coordinate.latitude
tempMapRegion.longitude = e.nativeEvent.coordinate.longitude
this.map.animateToRegion(this.newRegion(tempMapRegion));
// this.setState({ mapRegion: tempMapRegion })
}}
/>
</MapView>
So, what basically did the thing, was using the animateToRegion
property of the mapview. It basically animates the view to the mentioned region and then calls the onRegionChange
. I had stumbled upon this answer a number if times but it hadnt worked. Weirdly this only works in the build version and not while debugging, not on the emulator at least.
Thanks to https://stackoverflow.com/a/53836679/5379191 this answer for showing the way though.
newRegion(tempMapRegion) {
return {
...this.state.mapRegion,
...this.regionCoordinate(tempMapRegion),
};
}
regionCoordinate(tempMapRegion) {
return {
latitude: tempMapRegion.latitude,
longitude: tempMapRegion.longitude,
};
}