Auto-detect location react component using google geocoding and reverse geocoding in autocomplete
Auto detect React Component
AutoDetect : Dumb component
Make a state less component with the SVG included.
onClick handler is passed as props for this component which is defined in Higher order component (AutoComplete
)
import React from "react";
import PropTypes from "prop-types";
import Navigation from "./navigation.svg";const style = {
width: "14px"
};
const AutoDetect = (props) => {
return (
<div >
<span className="Datalist\_\_item h-48 c-blue flex flex-middle fs-14" onClick={ props.onClick } >
<Navigation className="Note\_\_icon mr-5" fill="#36c" style={ style } /> Current location
</span>
</div>
);
};
AutoDetect.propTypes = {
onClick: PropTypes.func
};
AutoDetect.defaultProps = {
onClick: null
};export default AutoDetect;
AutoComplete : Pure component
We call this._renderAutoDetect()
in render method of AutoComplete which in turns calls **<AutoDetect />**
component described above.
We will pass onClick handler to this
<AutoDetect onClick={ this.\_detectUserLocation } />
which will be passed as prop to AutoDetect component.
**_detectUserLocation**
is where we call browser object **navigator.geolocation.getCurrentPosition**
which will first prompt user to allow or deny location.
Browser prompt
If it is allowed then either success or error callback is called.
Error callback
this.geoError = (error) => {
switch (error.code) {
case error.TIMEOUT:
console.log("Browser geolocation error !\\n\\nTimeout.");
break;
case error.PERMISSION\_DENIED:
console.log("Only secure origins are allowed");
break;
case error.POSITION\_UNAVAILABLE:
console.log("Browser geolocation error !\\n\\nPosition unavailable.");
break;
default:
console.log(error.code);
break;
}
};
Success callback
this.geoSuccess = (position) => {
this.\_displayLocation(position.coords.latitude, position.coords.longitude);
};
The success callback **geoSuccess**
has position as parameter which contains user latitude and longitude.
Now we will call **_displayLocation**
passing these lat and long for Google reverse geocoding.
Google Reverse GeoCoding
\_geocodeAddress = (geocoder, latlng) => {
geocoder.geocode({ location: latlng }, this.\_geoCodeCallback);
}if (navigator.geolocation) {
this.\_displayLocation = (latitude, longitude) => {
const geocoder = new google.maps.Geocoder();
const latlng = new google.maps.LatLng(latitude, longitude);
this.\_geocodeAddress(geocoder, latlng);
};
From success callback of Geocoding , we called **_displayLocation**
where we will instantiate google map **Geocoder**
and call **maps.Latlng**
The callback after success is **_geoCodeCallBack**
This callback will have result of different address formats fetched from passed latitude and longitude.
We can fetch city from this result.
\_geoCodeCallback = (results, status, event) => {
const google = window.google; // eslint-disable-line
if (status === google.maps.GeocoderStatus.OK) {
if (results\[0\]) {
const add = results\[0\].formatted\_address;
const value = add.split(",");
const count = value.length;
const city = value\[count - 3\];
// here we can dispatch action to search by city name and autofill the autocomplete
} else {
console.log("address not found");
}
} else {
console.log(status);
}
}
Now we can dispatch an action to React Middleware or directly to store using connect to fetch the autocomplete result from the city.
const bindActionsToDispatch = dispatch =>
(
{
searchFlightAirports: (city, meta) => {
dispatch(<action\_creator name>(city, meta));
}
}
);
export default connect(null, bindActionsToDispatch)(Autocomplete);
Below is the entire code.
\_geoCodeCallback = (results, status, event) => {
const google = window.google; // eslint-disable-line
if (status === google.maps.GeocoderStatus.OK) {
if (results\[0\]) {
const add = results\[0\].formatted\_address;
const value = add.split(",");
const count = value.length;
const city = value\[count - 3\];
// here we can dispatch action to search by city name and autofill the autocomplete
} else {
console.log("address not found");
}
} else {
console.log(status);
}
}\_geocodeAddress = (geocoder, latlng) => {
geocoder.geocode({ location: latlng }, this.\_geoCodeCallback);
}\_detectUserLocation = (event) => {
// check for Geolocation support
const google = window.google; // eslint-disable-lineif (navigator.geolocation) {
this.\_displayLocation = (latitude, longitude) => {
const geocoder = new google.maps.Geocoder();
const latlng = new google.maps.LatLng(latitude, longitude);
this.\_geocodeAddress(geocoder, latlng);
};this.geoSuccess = (position) => {
this.\_displayLocation(position.coords.latitude, position.coords.longitude);
};this.geoError = (error) => {
switch (error.code) {
case error.TIMEOUT:
console.log("Browser geolocation error !\\n\\nTimeout.");
break;
case error.PERMISSION\_DENIED:
console.log("Only secure origins are allowed");
break;
case error.POSITION\_UNAVAILABLE:
console.log("Browser geolocation error !\\n\\nPosition unavailable.");
break;
default:
console.log(error.code);
break;
}
};
navigator.geolocation.getCurrentPosition(this.geoSuccess, this.geoError);
} else {
console.log("Geolocation is not supported for this Browser/OS.");
}
}\_renderAutoDetect = () => {
return (
<AutoDetect onClick={ this.\_detectUserLocation } />
);
}render() {
return (
<div className="Autocomplete">
<Input
autoFocus={ this.props.autoFocus }
focusDelay={ this.props.focusDelay }
name="autocomplete"
inputClassName="Autocomplete\_\_search mb-0"
value={ this.props.value }
onChange={ this.\_handleChange }
autoComplete="off"
placeholder={ this.props.placeHolder }
/>
this.\_renderAutoDetect()
</div>
);
}
}
Note: You will need to create Google API map key and include that in your website layout file.