using navigator geolocation with reactors - javascript

I'm trying to display geolocation variables position.coords.lat/long and I'm having trouble storing the values in a global scope. Here is the code:
var GeoLoco = React.createClass({
lat: 0,
long: 0,
handler: function(position) {
this.lat = position.coords.latitude;
this.long = position.coords.longitude;
console.log("Lat,Long: "+this.lat+","+this.long);
},
render: function() {
navigator.geolocation.getCurrentPosition(this.handler);
return <p>Lat,Long: {this.lat},{this.long}</p>;
}
});
console.log displays the location data, but this.lat and this.long render as 0

Even if your variable's values changed, you have to re-render your component to update what you're seeing.
The component's state does it for you.
More information here
By default, when your component's state or props change, your component will re-render.
So :
var GeoLoco = React.createClass({
getInitialState: function() {
return {lat: 0, long: 0};
},
handler: function(position) {
this.setState({
lat: position.coords.latitude,
long: position.coords.longitude
});
},
render: function() {
// If this.state.lat is not equal to 0, do not call again getCurrentPosition()
if (!this.state.lat)
navigator.geolocation.getCurrentPosition(this.handler);
return <p>Lat,Long: {this.state.lat},{this.state.long}</p>;
}
});
If you don't want to use state, you can call forceUpdate() at the end of your handler method.
handler: function(position) {
this.lat = position.coords.latitude;
this.long = position.coords.longitude;
console.log("Lat,Long: "+this.lat+","+this.long);
this.forceUpdate();
},

Related

How to add an index by storing an array in LocalStorage?

const getLocation = () => { //현재 위치 값 가져오는 함수
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success, error, option);
} else {
alert("위치정보를 사용할 수 있는 기기가 아닙니다.")
}
}
function success(position) {
let loca = localStorage.getItem("user_location");
if (loca === null) {
let dis = [];
let arr = [{
lat: position.coords.latitude,
lon: position.coords.longitude,
time: position.timestamp
}];
localStorage.setItem("user_location", JSON.stringify(arr));
localStorage.setItem("distance", dis);
} else {
loca = JSON.parse(loca);
localStorage.setItem("user_location", JSON.stringify(loca.concat(
{
lat: position.coords.latitude,
lon: position.coords.longitude,
time: position.timestamp
})));
setstate(loca);
console.log(state)
}
}
The location value is periodically retrieved every 15 seconds and stored in local storage.
However, not only the new values ​​are stored in the array, but the previously received values ​​are also stored.
For example
0: [{1}], -15 seconds
1: [{1}],
2: [{1},{1,2}], -15 seconds
3: [{1}],
4: [{1},{1,2}],
5: [{1},{1,2},{1,2,3}] -15 seconds
...
I want the newly retrieved value to be stored in a new index. How can I do it?
function success(position) {
let loca = localStorage.getItem("user_location");
if (loca === null) {
My prediction seems to be because I fetch the array (loca) before executing the if statement, but I don't know how to fix it.
Append existing value with what you get (current value):
localStorage.setItem(
'user_location',
JSON.stringify([
...JSON.parse(localStorage.getItem('user_location')),
{
lat: position.coords.latitude,
lon: position.coords.longitude,
time: position.timestamp,
},
])
);

React this.SetState is undefined - nested function

Making my first react app. I want to update the google maps api based on the user's location.
I am receiving the error "this is undefined". I understand using .bind(this) and wrapping in an arrow function but think this case is a bit different because I am setting state inside a nested function:
constructor(props) {
super(props);
this.state = {zip: null, lat: 40.5304 , lng: -100.6534 , zoom: 3.8 };
this.updateCurrentPosition= this.updateCurrentPosition.bind(this);
}
//...
updateCurrentPosition = () => {
navigator.geolocation.getCurrentPosition(success, error);
function success(pos) {
this.setState(`{lat: ${pos.coords.latitude}, lng: ${pos.coords.longitude}, zoom: ${3.8}`)
}
function error(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
};
}
ops = () => {
return {
center: { lat: this.state.lat, lng: this.state.lng },
zoom: this.state.zoom
}
};
Arrow functions automatically bind functions to the parent class. If a function is not binded, or not an arrow function, "this" will refer only to the function itself, even if it is nested. Your success function (and failure function too) is not bound to the parent class, as you have neither binded it or defined it as an arrow function.
The problem is that this is undefined under strict mode in Javascript. You can refer to this paragraph to read more http://2ality.com/2014/05/this.html
For your particular question, when you defined success and error, the two functions are not bound to parents.
The following modification by defining the functions as arrow functions will resolve your issue.
const success = (pos) => {
this.setState(`{lat: ${pos.coords.latitude}, lng: ${pos.coords.longitude}, zoom: ${3.8}`)
}
const error = (err) => {
console.warn(`ERROR(${err.code}): ${err.message}`);
};
So, I've instead passed the functions directly as arguments to the getCurrentPosition method and it seems to work fine.
updateCurrentPosition = () => {
navigator.geolocation.getCurrentPosition( (pos) => {
this.setState({ lat: pos.coords.latitude, lng: pos.coords.longitude, zoom: 1 })
},
(err) => {
console.warn(`ERROR(${err.code}): ${err.message}`)
}
)
}

i can't access data values from methods in my vue.js component?

I can’t access the values lat , lng from data() in maps() method.
my vue.js component
code link : https://gist.github.com/melvin2016/c8082e27b9c50964dcc742ecff853080
console image of lat,lng
enter image description here
<script>
import Vue from 'vue';
import navbarSec from './navbarSec.vue';
export default {
data(){
return{
lat: '',
lng: '',
mapState: window.mapState,
from:'',
to:'',
placesFrom:[],
placesTo:[]
};
},
components:{
'navbar':navbarSec
},
created(){
var token = this.$auth.getToken();
this.$http.post('http://localhost:3000/book',{},{headers: {'auth':token}}).then(function(data){
this.session = true;
})
.catch(function(data){
this.session = false;
this.$auth.destroyToken();
Materialize.toast(data.body.message, 6000,'rounded');
this.$router.push('/login');
});
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition((data)=>{
this.lat = data.coords.latitude;
this.lng = data.coords.longitude;
this.from=data.coords.latitude+' , '+data.coords.longitude;
});
}else{
Materialize.toast("Cannot Get Your Current Location !", 6000,'rounded');
}
},
mounted(){
if (this.mapState.initMap) {// map is already ready
var val = this.mapState.initMap;
console.log(val);
this.maps();
}
},
watch: {
// we watch the state for changes in case the map was not ready when this
// component is first rendered
// the watch will trigger when `initMap` will turn from `false` to `true`
'mapState.initMap'(value){
if(value){
this.maps();
}
},
from : function(val){
if(val){
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({input:this.from},data=>{
this.placesFrom=data;
});
}
},
to:function(val){
if(val){
var autoComplete = new google.maps.places.AutocompleteService();
autoComplete.getPlacePredictions({input:this.to},data=>{
this.placesTo=data;
});
}
}
},
methods:{
maps(){
var vm = this;
var lati = vm.lat;
var lngi = vm.lng;
console.log(lati+' '+lngi);
var map;
var latlng = {lat: lati, lng:lngi };
console.log(latlng);
this.$nextTick(function(){
console.log('tickkkk');
map = new google.maps.Map(document.getElementById('maplo'), {
zoom: 15,
center: latlng
});
var marker = new google.maps.Marker({
position: latlng,
map: map
});
});
}
}
}
</script>
This is happening because you're calling maps() in the mounted at which point, the navigator.geolocation.getCurrentPosition((data) => {}) code hasn't resolved. With that in mind, call this.maps() within the getCurrentPosition method i.e:
navigator.geolocation.getCurrentPosition((data)=>{
this.lat = data.coords.latitude;
this.lng = data.coords.longitude;
this.from=data.coords.latitude+' , '+data.coords.longitude;
this.maps()
});
I've not looked in detail but you might be able to change the bits within the maps() method to remove the nextTick stuff when you do this as you'll be calling it a lot later in the cycle at which point everything will have been rendered.

Can't set React state when getting user lat/long location

I'm trying to get the user's location (that works) and set it to the current state in a React component (this part doesn't). I've looked through a few answers on here and can't tell what I'm doing wrong.
Here's what I have:
class Container extends Component {
constructor() {
super()
this.state = {
location: {
lat: 0,
lng: 0
}
}
}
componentDidMount() {
navigator.geolocation.getCurrentPosition(
(position) => {
let lat = position.coords.latitude
let lng = position.coords.longitude
console.log("getCurrentPosition Success " + lat + lng) // logs position correctly
this.setState({
location: {
lat: lat,
lng: lng
}
})
},
(error) => {
this.props.displayError("Error dectecting your location");
console.error(JSON.stringify(error))
},
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000}
)
}
render() {
const location = this.state.location
return (
<div>
<Map center={location}/>
</div>
)
}
}
It looks similar to what other people have, and I've tried a few different ways, but I can't get the state to set. Is there something I'm missing or doing wrong?
The setState command is working fine.
Note that the get location is an async. call, and therefore the render() will be called twice. The first time it call, the lat/lng is zero.
You can add a logic to check it is zero and return null, if you want to render the output after getting the lat/lng from the geolocation services.

ionic angular factory return undefined

I got a view where I render a google map which then should check the location of the device periodically.
Controller
.controller('SearchCtrl', function($scope, $ionicLoading, TrackLocation) {
//document.addEventListener("deviceready", onDeviceReady, false);
//function onDeviceReady() {
//Loads Google Map
var mapOptions = {
center: new google.maps.LatLng(0,0),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false,
streetViewControl: false
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var myPost = TrackLocation.track();
console.log(myPost);
//}
})
Factory
.factory('TrackLocation', function($http, $cordovaGeolocation) {
return {
track: function() {
console.log("Started Tracking");
var lat, long;
var watchOptions = {
timeout : 3000,
enableHighAccuracy: true
};
var watch = $cordovaGeolocation.watchPosition(watchOptions);
watch.then(
null,
function(err) {
console.log(err);
return "lole";
},
function(position) {
lat = position.coords.latitude
long = position.coords.longitude
console.log(lat);
});
return {'lat': lat, 'long':long };
},
stop: function() {
}
};
})
Console Log
Started Tracking
Object {lat: undefined, long: undefined}
103 14.408132700000001
the myPost was return with an undefined value because it was called before the real value was pass on the lat.
Please help.
You should return just watch in your track method or return promise and than in success callback resolve this promise with lat and long values.

Categories