【问题标题】:Wait until useState object has value等到 useState 对象有值
【发布时间】:2022-01-10 12:25:34
【问题描述】:

我制作了一个自定义钩子,可用于获取用户位置并根据该信息在地图上找到最近的标记。

现在它可以工作,但它返回的第一个对象是useStates 默认值。响应如下所示:

{
  coordinates: { lat: '', lng: '' },
  loaded: false
}

第一次返回对象后,它开始正常工作:

{
  coordinates: { lat: 45.024335, lng: 19.277089 },
  loaded: true
}

所以基本上我不希望钩子发送没有值的空对象。我该如何解决这个问题?

const useGeoLocation = (markers) => {

  const [location, setLocation] = useState({
    loaded: false,
    coordinates: { lat: "", lng: "" },
  });

  const onSuccess = (location) => {
    // User location succesfully fetched, converting data format.
    const targetPoint = turf.point([
      location.coords.latitude,
      location.coords.longitude,
    ]);

    // Fetching data from markers parameter and converting data format.
    var arr = [];
    markers.map((marker) => arr.push(turf.point(marker.location)));
    var points2 = turf.featureCollection(arr);

    // Calculating which marker is nearest to targetPoint.
    var nearest = turf.nearestPoint(targetPoint, points2);

    // Setting location of nearest marker to usestate.
    setLocation({
      loaded: true,
      coordinates: {
        lat: nearest.geometry.coordinates[0],
        lng: nearest.geometry.coordinates[1],
      },
    });
  };

  const onError = () => {
    setLocation({
      loaded: true,
      coordinates: {
        lat: 65.024335,
        lng: 27.277089,
      },
    });
  };

  useEffect(() => {
    if (markers) {
      if (!("geolocation" in navigator)) {
        onError();
      }
      navigator.geolocation.getCurrentPosition(onSuccess, onError);
    }
  }, [markers]);

  return location;
};

【问题讨论】:

  • 您可以将位置初始化为空,然后它只是一个简单的检查
  • 那你希望它返回什么?由于它是异步操作,因此您无法从一开始就获得信息。您还知道由于加载的道具信息尚未加载。所以我不太明白。
  • 你想让钩子发送什么?您不能发送您没有的数据。因此,您必须使用默认值,以便在仍在获取数据时使用。无论是{loaded: false, coordinates: {lat: "", lng: ""}}{loaded: false, coordinates: {}}{loaded: false: coordinates: null}等。这些不必为空,您也可以使用默认坐标,例如坐标:{loaded: false, {lat: 65.024335, lng: 27.277089}}(坐标取自您的错误处理)。

标签: javascript reactjs react-hooks use-effect use-state


【解决方案1】:

除了将location 对象作为一个整体返回之外,您还可以将返回拆分为一个包含数据值、加载状态和错误消息的对象(如果需要)。例如:

const useGeoLocation = (markers) => {
  const [location, setLocation] = useState(undefined);
  const [error, setError] = useState("");

  const onSuccess = (location) => {
    // Rest of the success handler...
    setLocation({
      coordinates: {
        lat: nearest.geometry.coordinates[0],
        lng: nearest.geometry.coordinates[1],
      },
    });
  };

  const onError = () => {
    setLocation({
      coordinates: {
        lat: 65.024335,
        lng: 27.277089,
      },
    });
    setError("Some error message");
  };

  useEffect(() => {
    if (markers) {
      if (!("geolocation" in navigator)) {
        onError();
      }
      navigator.geolocation.getCurrentPosition(onSuccess, onError);
    }
  }, [markers]);

  return {
    data: location,
    isLoading: !location && !error,
    error: error,
  };
};

那么在调用钩子的时候可以这样做:

const {data, isLoading, error} = useGeoLocation();

在做任何事情之前检查data的值,或者isLoadingerror是否为假。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-20
    • 2020-02-15
    • 2020-08-15
    • 2020-02-26
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    相关资源
    最近更新 更多