I made a recursive loop, at the moment without a stopping criterium bus I don't think that should matter. I don't create any variable within the loop, and I just dont understand why it stops:
async function locagetter() {
return await Location.getCurrentPositionAsync({enableHighAccuracy: true});
}
async function calcdist(val) {
console.log("hoi");
val = await locagetter();
await SetDistance(getPreciseDistance(
{latitude: 51.493280, longitude: 4.294605 },
{latitude: val.coords.latitude, longitude: val.coords.longitude}));
calcdist(val);
}
I tried alot also promises, but i think it should work, I just need a continuous location refresh.
CodePudding user response:
If you need a continous refresh then why not just use an interval? As of now your recursion doesnt have a break condition so it might still run when the component unmounts (Im not sure about this so dont quote me) where as with an interval you can start stop it on unmounts:
const intervalId = useRef()
const startCoordinate = {latitude: 51.493280, longitude: 4.294605 }
const calcLocationDist = async (coordinate=startCoordinate)=>{
let currentCoordinate = await Location.getCurrentPositionAsync({
enableHighAccuracy: true
});
SetDistance(getPreciseDistance(coordinate,currentCoordinate)
}
useEffect(()=>{
intervalId.current = setInterval(()=>{
calcLocationDist();
},1000)
// for component unmounts
return ()=>{
clearInterval(intervalId.current)
}
},[])
You could take things a step further and create a useCurrentLocation hook. It would allow you do more without cluttering the component that uses it:
const defaultConfig = {
// interval updates in seconds
updateInterval=10,
}
export default function useCurrentLocation({onUpdate, one rror,updateInterval}=defaultConfig){
// track errors
const [error, setError] = useState(null);
const [value, setValue] = useState({});
// toggle the interval on and off
const [shouldUpdate, setShouldUpdate] = useState(true);
const intervalId = useRef()
const update = async ()=>{
try{
let loc = await Location.getCurrentPositionAsync({
enableHighAccuracy: true
});
setValue(loc);
onUpdate?.(loc);
} catch(err){
setError(err)
one rror?.(setShouldUpdate,error)
}
}
useEffect(()=>{
if(shouldUpdate){
intervalId.current = setInterval(()=>{
update()
},updateInterval*1000)
}
else
clearInterval(intervalId.current)
}
return ()=>{
clearInterval(intervalId.current)
}
},[shouldUpdate])
return {
value,
error,
shouldUpdate:setShouldUpdate
}
}
Then in the component that uses the location:
const startCoordinate = {latitude: 51.493280, longitude: 4.294605 };
const [permissionStatus, requestPermission] = Location.useForegroundPermissions();
const location = useCurrentLocation({
updateInterval:5,
onUpdate:newLocation=>{
SetDistance(getPreciseDist(startCoordinate,newLocation))
},
one rror:(error,shouldUpdate)=>{
console.log(error)
// stop interval
shouldUpdate(false)
}
});
// location.value is current location
console.log(location.value)
// location.error is last error
console.log(location.error)
// location.shouldUpdate is a function that will accept a boolean
// that will turn the interval on or off
useEffect(()=>{
// if permission is granted turn interval on
if(permissionStatus?.granted)
location.shouldUpdate(true)
else{
// turn interval off
location.shouldUpdate(false)
// if permission can be request again attempt to do so
if(permissionStatus.canAskAgain)
requestPermission()
}
},[permissionStatus])