3

I am using an older version of the capacitor geolocation, v1.3.1, and recently switched to the watchPosition implementation but occasionally that created a situation where the position is null or undefined even when the device is showing the location icon being active for the app. I tried to solve that by falling back to the slower getCurrentPosition function but still persists. Has anyone run into this issue before? Here is a gist of the hook.

https://gist.github.com/billpull/8bc6e49872cfee29aa5cef193b59c835

useCurrentPosition.ts

const useCurrentPosition = (): GeoWatchPositionResult => {
  const [position, setPosition] = useState<Position>();
  const [watchId, setWatchId] = useState("");
  const [error, setError] = useState();

  const clearWatch = () => {
    if (watchId) {
      clearPosition({ id: watchId });
      setWatchId("");
    }
  };

  const startWatch = async () => {
    if (!watchId) {
      const id = await watchPosition(async (pos: Position | null, err) => {
        if (err) {
          setError(err);
        }
        if (pos) {
          setPosition(pos);
        } else {
          const newPosition = await getCurrentPosition();
          setPosition(newPosition);
        }
      });
      setWatchId(id);
    }
  };

  useEffect(() => {
    startWatch();

    return () => clearWatch();
  }, []);

  return { currentPosition: position, error };
};

Even though the watchPosition is still returning location data on the interval I am getting a kCLErrorDomain error 1. which online says it means the permission was denied but thats not the case the phone was just in sleep mode. Is there a way to catch this error specifically? Should I clear the watch and restart it on this error?

Edit:

One attempt I made was to use a try catch in the watch, but I still have encountered this issue.

const useCurrentPosition = (): GeoWatchPositionResult => {
  const [position, setPosition] = useState<Position>();
  const [watchId, setWatchId] = useState("");
  const [error, setError] = useState();

  const clearWatch = () => {
    if (watchId) {
      clearPosition({ id: watchId });
      setWatchId("");
    }
  };

  const startWatch = async () => {
    if (!watchId) {
      const id = await watchPosition(async (pos: Position | null, err) => {
       try {
        if (err) {
          setError(err);
        }
        if (pos) {
          setPosition(pos);
        } else {
          const newPosition = await getCurrentPosition();
          setPosition(newPosition);
        }
       } catch (ex) {
         await requestPermission();
         clearWatch();
         await startWatch();
       }
      });
      setWatchId(id);
    }
  };

  useEffect(() => {
    startWatch();

    return () => clearWatch();
  }, []);

  return { currentPosition: position, error };
};
BillPull
  • 6,853
  • 15
  • 60
  • 99

1 Answers1

0

setState is an asynchronous function, so please pass to it an anonymous function:

if (pos) {
  setPosition(pos);
} else {
  const newPosition = await getCurrentPosition();
  setPosition(() => newPosition);
}
Yves
  • 252
  • 3
  • 6