'Unsubscribe from watchPositionAsync with useEffect return function
Using react native with expo-location for a mobile app, I would like to unsubscribe from Location.watchPositionAsync
which returns a promise with a remove()
method to unsubscribe.
I call the function within a useEffect hooks, but i don't know how to correctly return a cleanup function with the watchPositionAsync promise resolved.
Any suggestions?
import { useState, useEffect } from "react";
import { Text, View } from "react-native";
import * as Location from "expo-location";
export const GpsComponent = function () {
const [location, setLocation] = useState(null);
useEffect(() => {
const positionSubscription = async () => {
const positionSubscribe = await Location.watchPositionAsync(
{ accuracy: Location.LocationAccuracy.BestForNavigation },
(newLocation) => {
setLocation(newLocation);
}
);
return positionSubscribe;
};
/*return () => {
positionSubscription.remove();
console.log("Unsubscribed from WatchPositionAsync");
};*/
}, [setLocation]);
return (
<View>
<Text>{JSON.stringify(location)}</Text>
</View>
);
};
Solution 1:[1]
This will create the watchPositionAsync subscription and pass the correct remove function as the cleanup of the useEffect. A dummy subscription is created initially with a nop remove function.
useEffect(() => {
// nop subscription. in case not successful
let subscription = { remove: () => {} }
// subscribe async function
const subscribe = async () => {
return await Location.watchPositionAsync(
{ accuracy: Location.LocationAccuracy.Highest },
(newLocation) => {
setLocation(newLocation)
}
)
}
// return subscription promise
subscribe()
.then(result => subscription = result)
.catch(err => console.warn(err))
// return remove function for cleanup
return subscription.remove
}, [])
Solution 2:[2]
I finally found a way to unsubscribe to watchPositionAsync
using useRef
import { useState, useEffect, useRef } from "react";
import { Text, View } from "react-native";
import * as Location from "expo-location";
export const GpsComponent = function () {
const [location, setLocation] = useState(null);
const unsubscribe = useRef(() => undefined);
useEffect(() => {
const subscribe= async () => {
const positionSubscription = await Location.watchPositionAsync(
{ accuracy: Location.LocationAccuracy.BestForNavigation },
(newLocation) => {
setLocation(newLocation);
}
);
unsubscribe.current=()=>{positionSubscription?.remove()}
};
return ()=>{unsubscribe.current()}
}, []);
return (
<View>
<Text>{JSON.stringify(location)}</Text>
</View>
);
};
It 's also possible to use an object and modify a property after the async function's promise is resolved.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Scott Daniel |
Solution 2 | Fred |