watchPositionAsync() detect when location sharing is disabled

import { StatusBar } from "expo-status-bar";
import React, { useState, useEffect } from "react";
import { StyleSheet, Text, View } from "react-native";
import * as Location from "expo-location";
 
export default function App() {
  const [location, setLocation] = useState(null);
  const [errorMsg, setErrorMsg] = useState(null);
  const [locationEnabled, setLocationEnabled] = useState(false);
 
  useEffect(() => {
    Location.watchPositionAsync(
      {
        accuracy: Location.Accuracy.Highest,
        distanceInterval: 1,
        timeInterval: 10000,
      },
      (pos) => {
        setLocation(pos.coords);
      }
    )
      .then((locationWatcher) => {
        //set locationwatcher for removing
      })
      .catch((err) => {
        /*(async () => {
          let res = await Location.hasServicesEnabledAsync();
          console.log("watchpos location2: ", res);
          setLocationEnabled(res);
        })();*/
        console.log("watchpositon error: ", err.message);
        setErrorMsg(err.message);
      });
  }, []);
 
  useEffect(() => {
    console.log(locationEnabled);
  }, [locationEnabled, location]);
 
  let text = "Waiting..";
  if (errorMsg) {
    text = errorMsg;
  } else if (location) {
    text = JSON.stringify(location);
  }
 
  return (
    <View style={styles.container}>
      <Text style={styles.paragraph}>{JSON.stringify(location)}</Text>
    </View>
  );
}

In my example, the docs say, that watchPositionAync() subscribes to user location changes, so I thought the error when the location sharing is disabled it will be in the catch(), but it is not. If I disable location it just won’t get called, but if I enable it it will continue.

How can I check if the location was disabled? I tried using hasServicesEnabledAsync(), but I don’t know where to call it.

Perhaps try something like this:

  useEffect(() => {
    (async () => {
      await Location.hasServicesEnabledAsync();
      setLocationEnabled(true);
      console.log("location enabled");
    })();
  }, []);

  useEffect(() => {
    Location.watchPositionAsync(
[...]

The problem with this is that this check only when the component has mounted. To be precise, the watchPositionAsync() makes the component re-render, so hasServicesEnabledAsync() would be called too. But if I turn off the location sharing, watchPositionAsync() won’t get called,which means no re-render, so the hasServicesEnabledAsync() won’t change it’s value. Do you understand what I’m trying to say? :sweat_smile:

Hmmm… I suppose maybe you could call it periodically with the useInterval hook?

Well I don’t think this is the best solution, if I call a function with the hook every second can’t it ruin the performance or drain too much battery? Or if I call it every 5 seconds or even more then it would ruin the app, it wouldn’t be convenient to wait too long.