【问题标题】:Gatsby JS Uncaught TypeError React Google Maps APIGatsby JS Uncaught TypeError React Google Maps API
【发布时间】:2021-04-13 01:37:41
【问题描述】:

我在我的一个 Gatsby 网站中使用了 React Google Maps api。我创建了以下组件并将其导入到我的一个页面中。这是组件的代码。

import React, { useState } from "react"
import {
  GoogleMap,
  useLoadScript,
  Marker,
  InfoWindow,
} from "@react-google-maps/api"
import { useStaticQuery, graphql } from "gatsby"
import mapStyles from "./mapStyles"

const Indianapolis = {
  lat: 39.768402,
  lng: -86.158066,
}

const mapContainerStyle = {
  height: "100%",
  width: "100%",
}
const options = {
  styles: mapStyles,
  disableDefaultUI: true,
  zoomControl: true,
}

const Map = () => {
  const data = useStaticQuery(graphql`
    {
      allKmlPoint {
        edges {
          node {
            properties {
              name
              Longitude
              Latitude
              FRP_Project_Numbers
              description
              styleUrl
              styleHash
            }
            id
          }
        }
      }
    }
  `)

  const [selected, setSelected] = useState(null)

  const frpLocation = data.allKmlPoint.edges

  //console.log(process.env.GATSBY_GOOGLE_MAPS_API_KEY)
  const { isLoaded, loadError } = useLoadScript({
    googleMapsApiKey: process.env.GATSBY_GOOGLE_MAPS_API_KEY,
  })
  const mapRef = React.useRef()
  const onMapLoad = React.useCallback(map => {
    mapRef.current = map
    console.log(map)
  }, [])

  const onUnmount = React.useCallback(function callback(map) {
    console.log(map)
  }, [])

  if (loadError) return "Error"
  if (!isLoaded) {
    return "Loading..."
  }

  //console.log("comes here")
  return (
    <div className="map-container">
      <span className="top-text">Project</span>
      <span className="horizontal-line"></span>
      <span className="bottom-text">
        Locati<span className="full-color">o</span>ns
      </span>
      <span className="map-blurb">
        FRP has a project portfolio across a wide geographic region. Click the
        Map to Zoom and pan to the project locations for various market types.
      </span>
      <div className="map-wrapper">
        <GoogleMap
          zoom={8}
          center={Indianapolis}
          mapContainerStyle={mapContainerStyle}
          options={options}
          onUnmount={onUnmount}
          onLoad={onMapLoad}
        >
          {frpLocation.map(marker => (
            <Marker
              key={marker.node.id}
              position={{
                lat: parseFloat(marker.node.properties.Latitude),
                lng: parseFloat(marker.node.properties.Longitude),
              }}
              icon={{
                url: `icon_${marker.node.properties.styleUrl.slice(-6)}.svg`,
                origin: new window.google.maps.Point(0, 0),
                anchor: new window.google.maps.Point(15, 15),
                scaledSize: new window.google.maps.Size(30, 30),
              }}
              onClick={() => {
                setSelected(marker)
              }}
            />
          ))}

          {selected ? (
            <InfoWindow
              position={{
                lat: parseFloat(selected.node.properties.Latitude),
                lng: parseFloat(selected.node.properties.Longitude),
              }}
              onCloseClick={() => {
                setSelected(null)
              }}
            >
              <div>
                <p>{selected.node.properties.name}</p>
              </div>



            </InfoWindow>
          ) : null}
        </GoogleMap>
      </div>
    </div>
  )
}
export default Map

页面运行良好。但是,当我尝试从页面(有谷歌地图)移动到另一个页面(在 Gatsby 中)时,页面转换并不顺畅。盖茨比完全重新加载新页面。控制台给了我以下错误:

Uncaught TypeError: a is undefined
    ZU marker.js:48
    <anonymous> marker.js:45
    setTimeout handler*_.bn common.js:17
    <anonymous> marker.js:45
    H js:207
    trigger js:204
    remove js:207
    removeListener js:203
    unregisterEvent reactgooglemapsapi.esm.js:142
    unregisterEvents reactgooglemapsapi.esm.js:150
    componentWillUnmount reactgooglemapsapi.esm.js:2118
    wrappedMethod react-hot-loader.development.js:707
    React 27
    unlisten index.js:103
    unlisten index.js:101
    promise callback*componentDidMount/refs.unlisten< index.js:99
    navigate history.js:100
    navigate history.js:99
    navigate navigation.js:120
    promise callback*navigate navigation.js:84
    ___navigate navigation.js:162
    onClick index.js:256
    onClick index.js:477
    React 22
marker.js:48:38

控制台上有几个出现此错误的实例(我认为与地图上标记的数量一样多)。

我确信这是摆脱此错误的简单解决方法。有人可以帮忙吗

更新:根据@Ferran 所说,我使用了以下代码,仍然无法正常工作:

如你所说,我创建了一个 useState 钩子。


const [frpMap, setFrpMap] = useState(null)
mapRef.current = map
...
const onLoad = React.useCallback(function callback(map) {
    setFrpMap(map)  
  }, [])

const onUnmount = React.useCallback(function callback(map) {
    setFrpMap(null)
    mapRef.current = null
    //console.log(map)
  }, [])

我想我不确定如何使用 setFrpMap 挂钩中设置的地图变量来呈现 GoogleMap。

所以,当我在卸载时执行 setFrpMap(null) 时,什么都没有发生。

【问题讨论】:

    标签: javascript reactjs google-maps graphql gatsby


    【解决方案1】:

    您没有卸载地图,因此当路线更改时它会中断。这没有做任何事情:

      const onUnmount = React.useCallback(function callback(map) {
        console.log(map)
      }, [])
    

    我建议使用useState 钩子的方法,以便在需要时安装和卸载/处置地图:

    import React, { useState } from "react"
    import {
      GoogleMap,
      useLoadScript,
      Marker,
      InfoWindow,
    } from "@react-google-maps/api"
    import { useStaticQuery, graphql } from "gatsby"
    import mapStyles from "./mapStyles"
    
    const Indianapolis = {
      lat: 39.768402,
      lng: -86.158066,
    }
    
    const mapContainerStyle = {
      height: "100%",
      width: "100%",
    }
    const options = {
      styles: mapStyles,
      disableDefaultUI: true,
      zoomControl: true,
    }
    
    const Map = () => {
      const [map, setMap] = React.useState(null)
    
      const data = useStaticQuery(graphql`
        {
          allKmlPoint {
            edges {
              node {
                properties {
                  name
                  Longitude
                  Latitude
                  FRP_Project_Numbers
                  description
                  styleUrl
                  styleHash
                }
                id
              }
            }
          }
        }
      `)
    
      const [selected, setSelected] = useState(null)
    
      const frpLocation = data.allKmlPoint.edges
    
      //console.log(process.env.GATSBY_GOOGLE_MAPS_API_KEY)
      const { isLoaded, loadError } = useLoadScript({
        googleMapsApiKey: process.env.GATSBY_GOOGLE_MAPS_API_KEY,
      })
      const mapRef = React.useRef()
      const onMapLoad = React.useCallback(map => {
        mapRef.current = map
        setMap(map)
        console.log(map)
      }, [])
    
      const onUnmount = React.useCallback(function callback(map) {
        console.log(map)
        setMap(null)
      }, [])
    
      if (loadError) return "Error"
      if (!isLoaded) {
        return "Loading..."
      }
    
      //console.log("comes here")
      return (
        <div className="map-container">
          <span className="top-text">Project</span>
          <span className="horizontal-line"></span>
          <span className="bottom-text">
            Locati<span className="full-color">o</span>ns
          </span>
          <span className="map-blurb">
            FRP has a project portfolio across a wide geographic region. Click the
            Map to Zoom and pan to the project locations for various market types.
          </span>
          <div className="map-wrapper">
            <GoogleMap
              zoom={8}
              center={Indianapolis}
              mapContainerStyle={mapContainerStyle}
              options={options}
              onUnmount={onUnmount}
              onLoad={onMapLoad}
            >
              {frpLocation.map(marker => (
                <Marker
                  key={marker.node.id}
                  position={{
                    lat: parseFloat(marker.node.properties.Latitude),
                    lng: parseFloat(marker.node.properties.Longitude),
                  }}
                  icon={{
                    url: `icon_${marker.node.properties.styleUrl.slice(-6)}.svg`,
                    origin: new window.google.maps.Point(0, 0),
                    anchor: new window.google.maps.Point(15, 15),
                    scaledSize: new window.google.maps.Size(30, 30),
                  }}
                  onClick={() => {
                    setSelected(marker)
                  }}
                />
              ))}
    
              {selected ? (
                <InfoWindow
                  position={{
                    lat: parseFloat(selected.node.properties.Latitude),
                    lng: parseFloat(selected.node.properties.Longitude),
                  }}
                  onCloseClick={() => {
                    setSelected(null)
                  }}
                >
                  <div>
                    <p>{selected.node.properties.name}</p>
                  </div>
    
    
    
                </InfoWindow>
              ) : null}
            </GoogleMap>
          </div>
        </div>
      )
    }
    export default Map
    

    这个想法是最初将您的地图设置为 null 并将其设置在您的 onLoad 函数中:

      const onMapLoad = React.useCallback(map => {
        mapRef.current = map
        setMap(map)
        console.log(map)
      }, [])
    

    注意:根据您的需要调整 sn-p。

    由于回调接收地图作为参数,您可以将其与useState 挂钩一起使用。

    另一方面,卸载地图时使用相反的方式(onUnmount):

      const onUnmount = React.useCallback(function callback(map) {
        console.log(map)
        setMap(null) // alternatively use map.data=null
       
      }, [])
    

    同样的方法,虽然你不需要它,但你的回调正在接收地图,所以你可以将地图对象设置为null

    您可以查看docs了解更多详情。

    【讨论】:

    • 你说的很有道理。正如你所说,我创建了一个 useState 钩子。 code const [frpMap, setFrpMap] = useState(null) mapRef.current = map ... const onLoad = React.useCallback(function callback(map) { setFrpMap(map) }, []) const onUnmount = React.useCallback (function callback(map) { setFrpMap(null) mapRef.current = null //console.log(map) }, []) code 我想我不确定如何使用 setFrpMap 钩子中设置的 map 变量来渲染谷歌地图。因此,当我在卸载时执行 setFrpMap(null) 时,什么都没有发生。
    • 你能更新你最初的问题吗?读这样的代码是不可能的。
    【解决方案2】:
    const onUnmount = React.useCallback(function callback(map) {
        map.data = null
      }, [])
    

    成功了

    【讨论】:

      猜你喜欢
      • 2020-01-12
      • 1970-01-01
      • 1970-01-01
      • 2019-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-03
      • 1970-01-01
      相关资源
      最近更新 更多