Beginner here. I have a button that gets latitude and longitude using the geolocation API. I get the location fine on my console, but I'm having trouble showing them in a input box (so that I can then post the location information later). Below is my code for the component:
export class GetLocation extends Component{
constructor(){
super();
this.state = {
latitude: '',
longitude: ''
};
this.getMyLocation = this.getMyLocation.bind(this);
}
ComponentDidMount(){
this.getMyLocation();
}
getMyLocation = (e) => {
let location = null;
let latitude = null;
let longitude = null;
if (window.navigator && window.navigator.geolocation) {
location = window.navigator.geolocation
}
if (location){
location.getCurrentPosition(function (position) {
latitude = position.coords.latitude;
longitude= position.coords.longitude;
console.log(latitude);
console.log(longitude);
})
}
this.setState({latitude: latitude, longitude: longitude})
}
render(){
return(
<div>
<p>Your location is </p>
<Field name="latitude" component="input" onChange={this.getMyLocation}/>
<button type="button" onClick={this.getMyLocation}>Get Geolocation</button>
</div>
);
}
}
I'm using redux-form and this component is a part of a wizard form (in case you were wondering about the Field Component)
ComponentDidMount should be componentDidMount. I believe you have to set a value prop to your Field right?
Also, as #bennygenel mentioned, you don't need to bind getMyLocation in the constructor since you are already using arrow function (I did on my example, feel free to change it). In order to have access to this.state inside getCurrentPosition's callback, you either need to bind the success callback or make use of arrow function.
class App extends React.Component {
constructor() {
super()
this.state = {
latitude: '',
longitude: '',
}
this.getMyLocation = this.getMyLocation.bind(this)
}
componentDidMount() {
this.getMyLocation()
}
getMyLocation() {
const location = window.navigator && window.navigator.geolocation
if (location) {
location.getCurrentPosition((position) => {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude,
})
}, (error) => {
this.setState({ latitude: 'err-latitude', longitude: 'err-longitude' })
})
}
}
render() {
const { latitude, longitude } = this.state
return (
<div>
<input type="text" value={latitude} />
<input type="text" value={longitude} />
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Like the other answers say you need to pass longitude and latitude values to the input so you can be able to show but there is another problem. You are not setting the longitude and latitude in the right place.
if (location){
location.getCurrentPosition(function (position) {
latitude = position.coords.latitude;
longitude= position.coords.longitude;
console.log(latitude);
console.log(longitude);
this.setState({
latitude: latitude,
longitude: longitude
}); // you should set state when you have the values.
}.bind(this)); // you need to bind this so you can use setState
}
Related
I´m trying to re-render a google map based on a location(city). I enter the city in the input type, but nothing happens. Can anyone help me with this? I already tried a lot of things, but nothing happens. Regards,
https://pastebin.pl/view/e31aeb6a
[enter link description here][1]
You might be looking for something like this where you will use Geocoding API to Geocode the address from your input then once geocoded, it will get the coordinates and plot it to your map using Maps JavaScript API.
You might also, would like to check Places Autocomplete with Maps JavaScript API where it provides suggestion on the address you are searching for then renders the place you selected on the map.
Please note that if you want to use Google Maps API, you need to use an API key and usage of these APIs are billed accordingly.
Here is how I implemented it on React. Code snippet below:
import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';
var map;
const API_KEY = "PUT_API_KEY_HERE";
class GeocodingApp extends React.Component {
constructor(props) {
super(props);
this.renderMap = this.renderMap.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.handleClick = this.handleClick.bind(this);
this.state = {
input: ""
};
}
componentDidMount() {
if (!window.google) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = `https://maps.googleapis.com/maps/api/js?key=` + API_KEY + `&libraries=geometry,places`;
script.id = 'googleMaps';
script.async = true;
script.defer = true;
document.body.appendChild(script);
script.addEventListener('load', e => {
this.renderMap()
})
} else {
this.renderMap()
}
}
renderMap() {
const coords = { lat: 41.375885, lng: 2.177813 };
const el = document.getElementById("map");
if (el) {
map = new google.maps.Map(el, {
zoom: 16,
center: {
lat: coords.lat,
lng: coords.lng
}
});
return map;
} else {
return null;
}
}
handleInputChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleClick(event) {
const geocoder = new google.maps.Geocoder();
this.codeAddress(geocoder);
event.preventDefault();
}
//Handles Geocoding part
codeAddress(geocoder) {
var address = this.state.input;
geocoder.geocode({ address: address }, function(results, status) {
if (status === "OK") {
//'results[0].geometry.location' is the coordinates of the address you want to find
map.setCenter(results[0].geometry.location);
} else {
return null;
}
});
}
render() {
return (
<div >
<h1>ADD YOUR API KEY TO MAKE IT WORKIN</h1>
<input
id="input"
name="input"
value={this.state.input}
onChange={this.handleInputChange}
/>
<button id="submit" onClick={this.handleClick}>
{" "}
Search
</button>
<div id="map" />
</div>
);
}
}
ReactDOM.render(<GeocodingApp />, document.getElementById("app"));
I am using Google Maps React API. I am not sure what I am doing wrong, but latitude and longitude remain to be 0, 0 when I attempt to update with Axios.
import React, {Component} from 'react'
import {Map, InfoWindow, Marker, GoogleApiWrapper, mapEventHandler, markerEventHandler} from 'google-maps-react';
import axios from 'axios'
const mapStyle = {
width: '100%',
height: '90%'
}
export class MapContainer extends Component<{google}, { map: google.maps.Map<Element>, latitude: number, longitude: number}>{
onMapClicked: mapEventHandler;
onMarkerClick: markerEventHandler;
map?: google.maps.Map | google.maps.StreetViewPanorama
marker?: google.maps.Marker
onInfoWindowClose: any;
constructor(props){
super(props);
this.state = {
map: null,
latitude: 0,
longitude: 0
}
this.componentDidMount = this.componentDidMount.bind(this);
}
componentDidMount(){
axios
.get('https://api.##########.com/admin/user', {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer e-------------IU'
},
params: {
'userId':'c------------------------------------d'
}
})
.then(
resp => {
this.setState({
latitude: Number(resp.data.location.latitude),
longitude: Number(resp.data.location.longitude)
})
console.log("Before:" + this.state.latitude + " and " + this.state.longitude);
})
.catch(err => console.log(err))
}
render(){
console.log("After:" + this.state.latitude + " and " + this.state.longitude);
return(
<>
<Map google={google}
zoom={16}
draggable
initialCenter={{
lat: this.state.latitude,
lng: this.state.longitude
}}
onReady={(mapProps, map) => {
this.setState({ map: map as google.maps.Map})
}}
style={mapStyle}
onClick={this.onMapClicked}>
<Marker onClick={this.onMarkerClick}
title={`Location of ...`} />
<InfoWindow google={google}
map={this.map as google.maps.Map}
marker={this.marker}
visible>
<div>
<h1>Hello.</h1>
</div>
</InfoWindow>
</Map>
<p className="float-left md:ml-32 mt-64 sm:pt-32 lg:pt-32">
</p>
</>
)
}
}
const GoogleMap = GoogleApiWrapper({
apiKey: 'A------w'
})(MapContainer)
export default GoogleMap;
Basically, I have no idea how to use MapContainer / GoogleMaps to take props, so I am using axios within this class to set latitude and longitude to the state. I do have the same longitude and latitude in another folder, so that's an option for me to, but I don't mind doing this for now. However, the coordinates remain at (0, 0). Am I mixing up the order in which I do this or something?
Edit: By the way, it's the map itself that does not update, even if the other states do
This is because setState is asynchronous. So use state after setState may not be updated one.
You have to use callback for setState to get updated value.
Alternatively you can use componentDidUpdate to use updated state value.
So you have to do this:
this.setState(
{
latitude: Number(resp.data.location.latitude),
longitude: Number(resp.data.location.longitude),
},
() => {
console.log("Before:" + this.state.latitude + " and " + this.state.longitude);
}
);
I am learning react, and is trying to plot a map with mapbox. I am stuck with how to render elements seperatly.
In the render part, there is a <div/> element and a component <CityWeather/> wrapped. div is a reference to map. The <Cityweather /> is an info box which is supposed to display weather information based on lat and long. The app.js file render method is
render(){
console.log(this.state);
return(
<section>
<div className="map-container" ref={x => { this.mapContainer = x;}}/>
<CityWeather lat={this.state.lat} lng={this.state.lng} />
</section>
);
The componentDidMount() is
componentDidMount() {
this.getLocation();
mapboxgl.accessToken = "";
const { lng, lat, zoom } = this.state;
const map = new mapboxgl.Map({
container: this.mapContainer,
style: "mapbox://styles/mapbox/streets-v11",
center: [lng, lat],
zoom: zoom
});
map.on("moveend", () => {
const { lng, lat } = map.getCenter();
this.setState({
lng: lng.toFixed(4),
lat: lat.toFixed(4),
zoom: map.getZoom().toFixed(2)
});
});
}
The <CityWeather /> component
class CityWeather extends Component {
constructor(props) {
super(props);
this.state = {
name: ""
};
}
componentDidMount() {
console.log(this.props); // this logs only 1 time when the page loads
fetch("api?lat=" + this.props.lat +"&lon=" +this.props.lng + "&appid=")
.then(res => res.json())
.then(data => {this.setState({ name: data.name });
}); // get name from lat and long and store it in state
}
render() {
return (
<div className="city-weather">
<p>
City | <span className="city">
{this.state.name}</span>
</p>
</div>
);
}
}
On each event the console is logging the updated latitude, longitude and zoom. Also the <CityWeather/> is also rendered for Ist time. After that the component is not rendered on state change.
You have loaded weather data in componentDidMount. It will only run the first time that the component is rendered, Not on every state change.
This is the correct code:
class CityWeather extends Component {
constructor(props) {
super(props);
this.state = {
name: ""
};
}
componentDidMount() {
this.load();
}
load(){
console.log(this.props); // this logs only 1 time when the page loads
fetch("api?lat=" + this.props.lat + "&lon=" + this.props.lng + "&appid=")
.then(res => res.json())
.then(data => {
this.setState({ name: data.name });
}); // get name from lat and long and store it in state
}
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (this.props.lat !== prevProps.lat || this.props.lng !== prevProps.lng) {
this.load();
}
}
render() {
return (
<div className="city-weather">
<p>
City | <span className="city">
{this.state.name}</span>
</p>
</div>
);
}
}
Did you add a log in the listener? I think the method was not called because you did not move. you can use timer and some mock data to test the render.
I'm new to React and currently trying to learn how to use react-google-maps library. Tried to show a map with users geolocation as the initialCenter of the map.
This is my code:
import React from "react";
import { GoogleApiWrapper, Map } from "google-maps-react";
export class MapContainer extends React.Component {
constructor(props) {
super(props);
this.state = { userLocation: { lat: 32, lng: 32 } };
}
componentWillMount(props) {
this.setState({
userLocation: navigator.geolocation.getCurrentPosition(
this.renderPosition
)
});
}
renderPosition(position) {
return { lat: position.coords.latitude, lng: position.coords.longitude };
}
render() {
return (
<Map
google={this.props.google}
initialCenter={this.state.userLocation}
zoom={10}
/>
);
}
}
export default GoogleApiWrapper({
apiKey: "-----------"
})(MapContainer);
Insted of creating a map with users location I get an initialCenter of my default state values.
How can I fix it? Am I even using the lifecycle function right?
Thank you very much for your help
navigator.geolocation.getCurrentPosition is asynchronous, so you need to use the success callback and set the user location in there.
You could add an additional piece of state named e.g. loading, and only render when the user's geolocation is known.
Example
export class MapContainer extends React.Component {
state = { userLocation: { lat: 32, lng: 32 }, loading: true };
componentDidMount(props) {
navigator.geolocation.getCurrentPosition(
position => {
const { latitude, longitude } = position.coords;
this.setState({
userLocation: { lat: latitude, lng: longitude },
loading: false
});
},
() => {
this.setState({ loading: false });
}
);
}
render() {
const { loading, userLocation } = this.state;
const { google } = this.props;
if (loading) {
return null;
}
return <Map google={google} initialCenter={userLocation} zoom={10} />;
}
}
export default GoogleApiWrapper({
apiKey: "-----------"
})(MapContainer);
let lon, lat;
let weather;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
lat = position.coords.latitude;
lon = position.coords.longitude;
console.log(typeof lat)
});
}
class Button extends React.Component{
state = {latt: lat}
render(){
return(
<div>
{this.state.latt}
<h1>ss</h1>
</div>
)}}
class Appp extends React.Component {
render(){
return(
<Button />
)}
}
ReactDOM.render(<Appp />, mountNode)
what i did
When I console.log the variable I get a number but why cant I use it as a value in state. Even putting it inside an array makes no difference.
it should be this:
let lat, lon, weather;
class Calendar extends React.Component {
constructor(props){
super(props);
this.state = {
lat: null,
lon: null
}
this.updateLatLon = this.updateLatLon.bind(this);
}
updateLatLon(){
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
this.setState(() => {
return {lat: position.coords.latitude, lon: position.coords.longitude}
});
});
}
}
componentWillMount(){
this.updateLatLon();
}
render(){
return (
<div>
{this.state.lat}
</div>
)
}
}
You change the state by using setState()
navigator.geolocation.getCurrentPosition(function(position) {
this.setState({
lat: position.coords.latitude,
lon: position.coords.longitude
});
console.log(typeof lat)
});