Fortunately, I found a solution about React Native Google Maps with Autocomplete by https://mdmoin07.medium.com/react-native-google-maps-with-autocomplete-45a5617be2f5. I'm able to convert the code using functional components. Initially, my code seems to work to fetch address from react-native-google-maps-autocomplete but unfortunately, the map is not showing and gives an error.
ERROR Warning: Failed prop type: The prop region.latitude
is marked as required in MapView
, but its value is undefined
.
import React, { useEffect, useRef, useState } from 'react';
import { View, StyleSheet } from 'react-native';
//mport RNMapView, { Circle, Marker, Polyline } from 'react-native-maps';
import { getLocation, geocodeLocationByName } from '../services/location-service';
//import MapInput from '../services/MapInput';
import MyMapView from '../components/map/MapView';
import MapInput from '../components/map/MapInput';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
import MapView, { Marker } from 'react-native-maps';
function MapContainer({ coords }) {
/*
state = {
region: {}
};
*/
const [region, setState] = useState({});
useEffect(() => {
getInitialState();
}, []);
function getInitialState() {
getLocation().then(
(data) => {
console.log(data);
setState({
region: {
latitude: data.latitude,
longitude: data.longitude,
latitudeDelta: 0.003,
longitudeDelta: 0.003
}
});
}
);
}
function getCoordsFromName(loc) {
setState(region);
}
function onMapRegionChange(region) {
this.setState({ region });
}
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<GooglePlacesAutocomplete
placeholder='Search'
minLength={2} // minimum length of text to search
autoFocus={true}
returnKeyType={'search'} // Can be left out for default return key
listViewDisplayed={false} // true/false/undefined
fetchDetails={true}
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
getCoordsFromName(details.geometry.location);
console.log(data);
}
}
query={{
key: "API KEY",
language: 'en',
components: "country:ph",
}}
nearbyPlacesAPI='GooglePlacesSearch'
debounce={300}
/>
</View>
{
region['latitude'] ?
<View style={{ flex: 1 }}>
<MapView
style={{ flex: 1 }}
ref={mapRef}
region={region.latitude}
showsUserLocation={true}
onRegionChange={(reg) => onMapRegionChange(reg)} >
<Marker
coordinate={region.latitude} />
</MapView>
</View>
: null}
</View>
);
}
export default MapContainer;
These codes are class components from the reference I found.
import React, { useEffect, useRef, useState} from 'react';
import { View, StyleSheet } from 'react-native';
//mport RNMapView, { Circle, Marker, Polyline } from 'react-native-maps';
import { getLocation, geocodeLocationByName } from '../services/location-service';
//import MapInput from '../services/MapInput';
import MyMapView from '../components/map/MapView';
import MapInput from '../components/map/MapInput';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';
import MapView, {Marker} from 'react-native-maps';
class MapContainer extends React.Component {
state = {
region: {}
};
componentDidMount() {
this.getInitialState();
}
getInitialState() {
getLocation().then(
(data) => {
console.log(data);
this.setState({
region: {
latitude: data.latitude,
longitude: data.longitude,
latitudeDelta: 0.003,
longitudeDelta: 0.003
}
});
}
);
}
getCoordsFromName(loc) {
this.setState({
region: {
latitude: loc.lat,
longitude: loc.lng,
latitudeDelta: 0.003,
longitudeDelta: 0.003
}
});
}
onMapRegionChange(region) {
this.setState({ region });
}
render() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<GooglePlacesAutocomplete
placeholder='Search'
minLength={2} // minimum length of text to search
autoFocus={true}
returnKeyType={'search'} // Can be left out for default return key
listViewDisplayed={false} // true/false/undefined
fetchDetails={true}
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
this.getCoordsFromName(details.geometry.location);
console.log(data);
}
}
query={{
key: "API KEY",
language: 'en',
components: "country:ph",
}}
nearbyPlacesAPI='GooglePlacesSearch'
debounce={300}
/>
</View>
{
this.state.region['latitude'] ?
<View style={{ flex: 1 }}>
<MapView
style={{ flex: 1 }}
region={this.state.region}
showsUserLocation={true}
onRegionChange={(reg) => this.onMapRegionChange(reg)} >
<Marker
coordinate={this.state.region} />
</MapView>
</View>
: null}
</View>
);
}
}
export default MapContainer;
Thank you for kindly answering my question. I'm from the Philippines. Maraming Salamat po.
CodePudding user response:
I have resolved your issue for converting it class to functional component. Please check the code and try to re run it.
import React, { useEffect, useRef, useState } from "react";
import { View, StyleSheet } from "react-native";
//mport RNMapView, { Circle, Marker, Polyline } from 'react-native-maps';
import {
getLocation,
geocodeLocationByName,
} from "../services/location-service";
//import MapInput from '../services/MapInput';
import MyMapView from "../components/map/MapView";
import MapInput from "../components/map/MapInput";
import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";
import MapView, { Marker } from "react-native-maps";
function MapContainer({ coords }) {
const [region, setRegion] = useState({
latitude: '',
longitude: '',
latitudeDelta: 0.003,
longitudeDelta: 0.003,
});
useEffect(() => {
getInitialState();
}, []);
function getInitialState() {
getLocation().then((data) => {
console.log(data);
setRegion({
latitude: data.latitude,
longitude: data.longitude,
latitudeDelta: 0.003,
longitudeDelta: 0.003,
});
});
}
function getCoordsFromName(loc) {
setRegion({
latitude: loc.latitude,
longitude: loc.longitude,
latitudeDelta: 0.003,
longitudeDelta: 0.003,
});
}
function onMapRegionChange(getRegion ) {
setRegion(getRegion);
}
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<GooglePlacesAutocomplete
placeholder="Search"
minLength={2} // minimum length of text to search
autoFocus={true}
returnKeyType={"search"} // Can be left out for default return key
listViewDisplayed={false} // true/false/undefined
fetchDetails={true}
onPress={(data, details = null) => {
// 'details' is provided when fetchDetails = true
getCoordsFromName(details.geometry.location);
console.log(data);
}}
query={{
key: "API KEY",
language: "en",
components: "country:ph",
}}
nearbyPlacesAPI="GooglePlacesSearch"
debounce={300}
/>
</View>
{ region ? (
<View style={{ flex: 1 }}>
<MapView
style={{ flex: 1 }}
ref={mapRef}
region={region}
showsUserLocation={true}
onRegionChange={(reg) => onMapRegionChange(reg)}
>
<Marker coordinate={{ latitude : region.latitude , longitude : region.longitude }}/>
</MapView>
</View>
) : null}
</View>
);
}
export default MapContainer;
EDIT Answer
For Google places autocomplete you are getting undefined because you not saving it from correct value from response. Save it like below : (check console.log of data & details as well)
onPress={(data, details = null) => {
setRegion({
latitude: details.geometry.location.lat,
longitude: details.geometry.location.lng,
latitudeDelta: 0.003,
longitudeDelta: 0.003,
});
}}
For map issue you can give any default values in useState for latitude and longitude
const [region, setRegion] = useState({
latitude: 22.5726,
longitude: 88.3639,
latitudeDelta: 1,
longitudeDelta: 1,
});
With the given code I can only get this much idea about your issues, if you are facing the issue after this too, then please provide full code.
CodePudding user response:
Please try initialRegion
instead of region in the MapView component and I would also define a whole region object with latitude, longitude and respective deltas.