I want to use mapview marker for show direction/route between user location and destination in react-native and a json service that gave the route as points.
now i want when user moves and her location changes, something like OnCoordinateChange for marker coordinate, call a function so i can send real-time start-point location to the router service and get new direction based on new location.
How can i do this?
here is some parts of my code:
(don't pay attention to that piece of #$%# code between two comment blocks!)
componentDidMount() {
//User Location
navigator.geolocation.getCurrentPosition(
position => {
fetch('https://api.openrouteservice.org/v2/directions/foot-walking?api_key='+ OsmDirectionApiKet +'&start='+position.coords.longitude+','+position.coords.latitude+'&end={}')
.then((response) => response.json())
.then((responseJson) => {
/*********
Began some of code that just me and god can understand why and has nothing effect on question!!!
**********/
var PolylineGetCoordinates = responseJson.features[0].geometry.coordinates;
var PolylineFinalCoordinates = [];
for(i=0;i<PolylineGetCoordinates.length;i++){
var obj = {};
obj.longitude = PolylineGetCoordinates[i][0];
obj.latitude = PolylineGetCoordinates[i][1];
PolylineFinalCoordinates.push(obj);
}
/*********
End some of $%## code!!!
*********/
this.setState({
PolylineCoordinates :PolylineFinalCoordinates
});
})
.catch((error) => {
console.error(error);
});
},
error => {
this.setState({
error: 'error'
});
}
);
}
//-------------------
<Polyline coordinates={PolylineCoordinates} />
well found a {SIMPLE} solution!
just moved the codes in componentDidMount() in another function, and changed the codes in componentDidMount to:
componentDidMount() {
this.getCurrentLocation;
setInterval(this.getCurrentLocation, 500);
}
and added this line to constructor:
this.getCurrentLocation = this.getCurrentLocation.bind(this);
Related
Im working with my friends on a app project and we find an issue many times when we tring to set a use state and the console log the variable, i've looking for a solution in the website and saw that the reason is that the usestate is an async awiat which means the variable that i set in the use state isn't immidatly set in it, so i tried many solution that i found in the websites but none of them work for me.
in the screenShot you can see that the json variable is in console log before and the set varaible doesn't show after the setActiveUser , any help?
Thanks!
If you want to do something upon setting state then your best bet is to use the useEffect hook from React and adding your state in the dependency array. This will then call the function in your useEffect every time the state changes. See below a rough example:
import { Text } from 'react-native';
const MyComponent = () => {
const [activeUser, setActiveUser] = useState(null);
useEffect(() => {
// This should log every time activeUser changes
console.log({ activeUser });
}, [activeUser]);
const fetchAuthentication = async user => {
var flag = false;
await fetch('/api/authUser/', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user),
})
.then(res => {
res.ok && (flag = true);
return res.json();
})
.then(json => {
if (flag) {
setActiveUser(json);
}
})
.catch(error => console.error(error));
return flag;
};
return <Text>Hi</Text>;
};
Full documentation: https://reactjs.org/docs/hooks-effect.html
Setup the huawei location kit for getting device position overtime when apps in use, followed the setup from https://developer.huawei.com/consumer/en/doc/HMS-Plugin-Guides-V1/config-agc-0000001050197382-V1
we don't have real huawei device, we're using cloud debugging
Try implement to watch the gps location overtime with all these syntax
// ------ Parent ------
// this put on the parent useEffect
HMSLocation.LocationKit.Native.init()
.then(() => console.log('----------Success Initialize----------'))
.catch((err) => alert(err.message))
// ------ Child ------
const stopWatchingLocation = () => {
if (hasHms) {
HMSLocation.FusedLocation.Events.removeFusedLocationEventListener(
(res: LocationResult) => console.log('remove add listener', res),
)
}
}
const startWatchingLocation = async () => {
if (hasHms) {
HMSLocation.FusedLocation.Native.requestLocationUpdatesWithCallbackEx(
hwGeolocationOptions,
)
.then((res) => console.log('success request', res))
.catch((error) => console.log('failed request', error))
HMSLocation.FusedLocation.Events.addFusedLocationEventListener(
(res: LocationResult) => console.log('result', res.lastHWLocation)
)
}
}
// implementation of add & remove event listener
useEffect(() => {
startWatchingLocation() // inside here invoke addFusedLocationEventListener
return stopWatchingLocation // inside here invoke, cleanup function removeFusedLocationEventListener
}, [])
The code successfully invoke the init, requestLocationUpdatesWithCallbackEx, but console log from addFusedLocationEventListener never invoke
Already turn on hms core app permission for location, hasPermission also returned true
Tried the locationRequest options from problem with react native #hmscore/react-native-hms-location comments, still not working
How we can fix these??
I think it might be a usage issue. The function of addingFusedLocationEventListener is to add FusedLocationEvent Listener. This function is triggered only when FusedLocationEvent happen.
In your description, delete removeFusedLocationEventListener after addFusedLocationEventListener, the added listener is also deleted.
In addition, you are advised to use independent functions instead of directly defining them in input parameters.
handleLocationUpdate = (locationResult) => { console.log(locationResult); this.setState({ locationCallbackResult: locationResult }); }
requestLocationCallbackWithListener = () => {
HMSLocation.FusedLocation.Native.requestLocationUpdatesWithCallbackEx(locationRequest)
.then((res) => this.setState({ reqCode: res.requestCode }))
.catch((err) => alert(err.message));
HMSLocation.FusedLocation.Events.addFusedLocationEventListener(this.handleLocationUpdate);
this.setState({ autoUpdateEnabled: true });
};
I have methods that benefit each other and I want one of them to start after the other, but it doesn't work exactly the way I want it. In another question, I used async and await in a normal method, but I did not manage to use google APIS and nested functions.
async componentDidMount() {
await this.getCityList();
console.log(this.state.cities)
await this.currentLocation();
await this.getVenueInformation();
}
At this point, the first function works correctly and after passing the required ones, it goes to the 2nd method. In the same way, I have to put the inputs of the 2nd method into the 3rd method, but I failed.
Current location method:
currentLocation() {
Geocoder.init(...);
Geolocation.getCurrentPosition((position) => {
this.getCurrentLoc(position.coords.latitude, position.coords.longitude),
this.setState({
region: {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
},
error: null,
});
}, (error) => this.setState({ error: error.message }), { enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 });
}
I want my location with the above method, then I get the address information with getcurrentloc method and I plan to show some places in the vicinity in accordance with that information. However, I could not make this system work sequentially and my address is always null.
getCurrentLoc(lat, longt) {
Geocoder.from(lat, longt)
.then(json => {....
this.setState({...},
this.getLocIDS(cityName, districtName, neighborhoodName)
);
})
.catch(error => console.warn(error));
}
at this point, I get the address from the database by address to pull the id information.
getLocIDS(cityName, districtName, neighborhoodName) {
let link = ..;
fetch(link)
.then(response => response.json())
.then(res => {
this.setState({,,,,,,})
})
.catch(error => console.warn(error));
}
lastly, I want to capture the venue information, but at this point the data is entered as -1 in the database. -1 is my initial state value. I'm sure all methods work correctly, but since the processes don't run sequentially, my space search method works before updating the data in the previous functions state.
getVenueInformation() {
let link = ...
fetch(link)
.then(response => response.json())
.then(venues => {
this.setState({
markers: venues,
isLoading: false,
})
})
};
database input return: >>>>> SELECT * FROM mekanlar WHERE mekanlar.mahalle_no="-1";
You don't show how you pass the information from one method to the other.
If you do it by use of this.state, that is where your problem is.
this.setState will not update the state synchronously. So you might not have the right value in this.state in your next function call.
To make sure the data flow is correct, it makes more sense to return the values explicitly, even if you do setState internally.
async componentDidMount() {
const cityList = await this.getCityList();
console.log(cityList)
const location = await this.currentLocation(cityList);
const venueInformation = await this.getVenueInformation(location);
}
I'm trying to use react native Geolocation to getCurrentPosition and then as soon as the position is returned, use react native geocoder to use that position to get the location. I'm using redux-observable epics to get all of this done.
Here are my two epics:
location.epic.js
import { updateRegion } from '../map/map.action'
import Geocoder from 'react-native-geocoder'
export const getCurrentLocationEpic = action$ =>
action$.ofType(GET_CURRENT_LOCATION)
.mergeMap(() =>
Observable.fromPromise(Geocoder.geocodePosition(makeSelectLocation()))
.flatMap((response) => Observable.of(
getCurrentLocationFulfilled(response)
))
.catch(error => Observable.of(getCurrentLocationRejected(error)))
)
export const getCurrentPositionEpic = action$ =>
action$.ofType(GET_CURRENT_POSITION)
.mergeMap(() =>
navigator.geolocation.getCurrentPosition(
(position) => Observable.of(
updateRegion(position),
getCurrentLocation(position)
),
error => Observable.of(getCurrentPositionRejected(error)),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
).do(x => console.log(x))
).do(x => console.log(x))
As soon as the app starts, this code executes:
class Vepo extends Component {
componentDidMount() {
const { store } = this.context
this.unsubscribe = store.subscribe(() => { })
store.dispatch(fetchCategories())
store.dispatch(getCurrentPosition())
}
fetchCategories() is an action that has an epic too, but that is working. dispatching the getCurrentPosition() action runs through the epic above. The only output that I can see is that my reducer handles getLocationRejected() as it console logs this:
there was an issue getting your current location: Error: invalid position: {lat, lng} required
at Object.geocodePosition (geocoder.js:15)
at MergeMapSubscriber.project (location.epic.js:17)
at MergeMapSubscriber._tryNext (mergeMap.js:120)
at MergeMapSubscriber._next (mergeMap.js:110)
at MergeMapSubscriber.Subscriber.next (Subscriber.js:89)
at FilterSubscriber._next (filter.js:88)
at FilterSubscriber.Subscriber.next (Subscriber.js:89)
at Subject.next (Subject.js:55)
at Object.dispatch (createEpicMiddleware.js:72)
at Object.dispatch (devTools.js:313)
Here is my reducer:
const searchPage = (
initialLocationState = initialState.get('searchForm').get('location'),
action: Object): string => {
switch (action.type) {
case GET_CURRENT_LOCATION_FULFILLED: {
return action.payload
}
case GET_CURRENT_LOCATION_REJECTED: {
console.log('there was an issue getting your current location: ',
action.payload)
return initialLocationState
}
case GET_CURRENT_POSITION_REJECTED: {
console.log('there was an issue getting your current position: ',
action.payload)
return initialLocationState
}
default:
return initialLocationState
}
}
Is there anything obvious I am doing wrong? My attempt to debug by adding .do(x => console.log(x)) does nothing, nothing is logged to the console. updateRegion() never does fire off because that dispatches an action and the reducer UPDATE_REGION never executes. But the execution must make it into the success case of getCurrentPosition() eg:
(position) => Observable.of(
updateRegion(position),
getCurrentLocation(position)
),
must execute because the getCurrentLocation(position) does get dispatched.
Where am I going wrong?
What would be your technique for using an epic on a function which takes a callback function? getCurrentPosition() takes a callback and the callback handles the payload. Basically if you remove Observable.of( from inside getCurrentPosition(), that's how getCurrentPosition() is correctly used - and has been working for me without redux-observable.
Wrapping anything in a custom Observable is fairly simple, very similar to creating a Promise except Observables are lazy--this is important to understand! RxJS Docs
In the case of geolocation, there are two main APIs, getCurrentPosition and watchPosition. They have identical semantics except that watchPosition will call your success callback every time the location changes, not just a single time. Let's use that one since it's natural to model it as a stream/Observable and most flexible.
function geolocationObservable(options) {
return new Observable(observer => {
// This function is called when someone subscribes.
const id = navigator.geolocation.watchPosition(
(position) => {
observer.next(position);
},
error => {
observer.error(error);
},
options
);
// Our teardown function. Will be called if they unsubscribe
return () => {
navigator.geolocation.clearWatch(id);
};
});
}
geolocationObservable({ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 })
.subscribe(
position => console.log(position),
e => console.error(e)
);
// will log every time your location changes, until you unsubscribe
Since it's now an Observable, if you only want the current location you can just do .take(1).
So using it inside your epic might be like this
// If you want, you could also use .share() to share a single
// underlying `watchPosition` subscription aka multicast, but
// that's outside the scope of the question so I don't include it
const currentPosition$ = geolocationObservable({
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000
});
export const getCurrentPositionEpic = action$ =>
action$.ofType(GET_CURRENT_POSITION)
.mergeMap(() =>
currentPosition$
.take(1) // <----------------------------- only the current position
.mergeMap(position => Observable.of(
updateRegion(position),
getCurrentLocation(position)
))
.catch(error => Observable.of(
getCurrentPositionRejected(error)
))
);
As a side note, you might not need to dispatch both updateRegion() and getCurrentLocation(). Could your reducers just listen for a single action instead, since they both seem to be signalling the same intent?
I need to pass some data from one screen to another, but I don't know how to do it. I've searched and I read about Redux, but it is a bit complicated since I never used it and most of the tutorials are confusing for a newcomer. But if I could do it without Redux, that would be better.
So, when I click in a button, It runs this:
onSearch() {
var listaCarros = fetch(`URL`, {
method: 'GET',
})
.then((response) => { return response.json() } )
.then((responseJson) => {
console.log(responseJson)
})
}
and I want to pass the data I get from this, to another screen.
Im using router-flux, if that matters.
you can save the response in state of your current component like
onSearch() {
var listaCarros = fetch(`URL`, {
method: 'GET',
})
.then((response) => { return response.json() } )
.then((responseJson) => {
console.log(responseJson);
/*for react-native-router-flux you can simply do
Actions.secondPage({data:responseJson}); and you will get data at SecondPage in props
*/
this.setState({
dataToPass :responseJson
});
})
}
then below in return like you want to pass data to a new component having named as SecondPage, you can do it in following way
render(){
return(
{this.state.dataToPass && <SecondPage data ={this.state.dataToPass}>} //you will get data as props in your second page
);
}