React get object-values outside of .then // 从地理编码中创建地图标记

React get object-values outside of .then // create map markers out of geocodes

我评论了我的代码以明确应该发生什么。我尝试了几个小时来从地理编码中创建标记,但我似乎无法弄清楚如何从承诺中提取值。我摆弄过 useState 和 useEffect,但都没有用。

const GMap = eventList => {
  return (
    <GoogleMap defaultZoom={10} defaultCenter={{ lat: 51.62919, lng: 7.3928 }}>
      {
          // Map through location-strings in eventList
          eventList.eventList.map(event => {
              // Get all geocodes
        Geocode.fromAddress(event.city).then(
          response => {
            const { lat, lng } = response.results[0].geometry.location;
            console.log(lat, lng);
          },
          error => {
            console.error(error);
          }
        );
        return (
            // Create marker for every geocode (lat/lng pair)
          <Marker
            key={event._id}
            position={{
              lat: 51.62919, // How to insert the lat and lng values from response instead?
              lng: 7.3928
            }}
          />
        );
      })}
    </GoogleMap>
  );
};

感谢您的帮助,即使一开始看起来微不足道,现在还没有解决这个问题真的很令人沮丧。

您可以使用 async-await 从同步的 Promise 中获取响应:

eventList.eventList.map(async event => {
   // Get all geocodes
   const rs = await Geocode.fromAddress(event.city)

   // Path to location. this path example could be wrong
   const { lat, lng } = rs.results[0].geometry.location 

   return (
      <Marker
          key={event._id}
          position={{
              lat: lat,
              lng: lng
         }}
      />
   );
})
const GMap = ({ eventList }) => {
  const [markers, setMarkers] = React.useState([]);

  React.useEffect(() => {
    eventList.forEach(async event => {
      const response = await Geocode.fromAddress(event.city);
      const { lat, lng } = response.results[0].geometry.location;

      const marker = (
        <Marker
          key={event._id}
          position={{
            lat,
            lng
          }}
        />
      );

      setMarkers(prevMarkers => [...prevMarkers, marker]);
    });
  }, [eventList]);

  return (
    <GoogleMap defaultZoom={10} defaultCenter={{ lat: 51.62919, lng: 7.3928 }}>
      {markers}
    </GoogleMap>
  );
};
eventList.forEach(async event => {
      const response = await Geocode.fromAddress(event.city);

我们将遍历 eventList 并像每次 Geocode.fromAddress returns 一样处理结果,而不是在 map 中处理。地图的问题是您限制自己在显示任何内容之前先处理整个地图。此方法允许您在标记返回时呈现它们。

setMarkers(prevMarkers => [...prevMarkers, marker]);

使用 useState 的回调,我们使用之前的 markers 并创建一个新数组,将之前的标记附加到它,因此它会随着每个 Geocode.fromAddress(event.city); 慢慢建立起来返回。

这里有一个可用的 CodeSandbox https://codesandbox.io/s/wizardly-paper-3eu03 我不得不删掉 GoogleMapMarkersGeocode.

Geocode,为了模拟真实世界,有一个随机的 setTimeout,所以你可以看到每个结果都准备好了。