Await for userlocation before calculating distance - Refactor to async function

Viewed 37

In my app I need to calculate the distance between the current user and the location of events.

I used this function in previous projects and this worked for me since userlocation was determined beforehand.

In my app now it's a little bit different since the events must be filtered immediately after login on the homepage, also where userlocation is still to be determined.

So it's a matter of making my code below asynchronous so that calculation is started after userLat and userLon contain there values

const [userLat, setUserLat] = useState(localStorage.getItem('userLat'))
const [userLon, setUserLon] = useState(localStorage.getItem('userLon'))


useEffect(() => {
    data?.forEach((el) => {
      Geocode.fromAddress(
        `${el.street} ${el.houseNumber}, ${el.zip} ${el.city}`
      )
        .then((res) => {
          let dis = getDistance(
            {
              latitude: parseFloat(res.results[0].geometry.location.lat),
              longitude: parseFloat(res.results[0].geometry.location.lon),
            },
            {
              latitude: parseFloat(userLat), // Not available right away
              longitude: parseFloat(userLon), // Not available right away
            }
          );
          console.log(dis); // this return NaN since userLat & userLon values aren't available yet
        })
        .catch((err) => console.log(err));
    });
  }, [data]);

So the geocode function should be executed as soon as userLat and userLon are available.

I have tried a few things turning it into an async function and trying to await the userLat en userLon values but without success.

Could somebody point me in the right direction about how to wait for Geocode.fromAddress until userLat en userLon values have been determined by geolocation api?

Thanks in advance!

1 Answers

While you can't call hooks within conditionals, you can include conditional checks within your hooks!

If you have an effect that needs to run based on data, userLat, and userLon, then include those as dependencies and include checks within your effect:

const [userLat, setUserLat] = useState(localStorage.getItem('userLat'));
const [userLon, setUserLon] = useState(localStorage.getItem('userLon'));

useEffect(
  () => {
    // Only calculate distance if coords are available
    if (userLat && userLon) {
      data?.forEach((el) => {
        Geocode.fromAddress(`${el.street} ${el.houseNumber}, ${el.zip} ${el.city}`)
          .then((res) => {
            let dis = getDistance(
              {
                latitude: parseFloat(res.results[0].geometry.location.lat),
                longitude: parseFloat(res.results[0].geometry.location.lon),
              },
              {
                latitude: parseFloat(userLat),
                longitude: parseFloat(userLon),
              }
            );

            // Do something with `dis` here...
          })
          .catch((err) => console.log(err));
      });
    }
  },
  // Re-run effect when these variables update
  [data, userLat, userLon]
);

Related