在计算距离之前等待用户位置 - 重构为异步函数

Await for userlocation before calculating distance - Refactor to async function

在我的应用程序中,我需要计算当前用户与事件位置之间的距离。

我在以前的项目中使用过这个功能,这对我有用,因为用户位置是事先确定的。

在我的应用程序中现在有点不同,因为必须在登录主页后立即过滤事件,而且用户位置仍有待确定。

所以我的代码要低于 asynchronous 以便在 userLatuserLon 包含值

之后开始计算
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]);

所以 geocode function 应该在 userLatuserLon 可用时立即执行。

我尝试了一些方法将它变成 async function 并尝试 await userLat en userLon 值但没有成功。

有人能给我指出正确的方向,关于如何 waitGeocode.fromAddress 直到 userLat en userLon 值已由地理定位 api 确定?

提前致谢!

虽然你不能 call hooks within conditionals,但你可以在你的钩子中包含条件检查!

如果您有一个效果需要 运行 基于 datauserLatuserLon,则将这些作为依赖项包括在内,并在您的效果中包括检查:

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]
);