在React中接入Google Maps API实现两点路线计算相关问题求助
报错原因&解决方案
核心报错原因
- DOM渲染时机不匹配:你在组件顶层直接执行地图初始化、查询DOM元素的逻辑,此时组件的JSX还没渲染到真实DOM上,
document.getElementById("googleMap")、document.getElementById("from")拿到的都是null,直接调用相关API必然报错。
- DOM渲染时机不匹配:你在组件顶层直接执行地图初始化、查询DOM元素的逻辑,此时组件的JSX还没渲染到真实DOM上,
- 谷歌SDK加载时机问题:直接在组件顶层声明
const google = window.google,如果谷歌地图SDK还没加载完成,window.google是undefined,调用google.maps相关API直接报错。
- 谷歌SDK加载时机问题:直接在组件顶层声明
- 事件绑定错误:你写的
onClick={getLocation()}、onClick={calcRoute()}是组件渲染时直接执行函数,不是点击后才执行,此时DOM还没生成,直接触发报错。
- 事件绑定错误:你写的
- 重复初始化地图:函数组件每次重渲染都会执行顶层代码,会反复创建地图实例,引发冲突报错。
- 属性书写不规范:React中HTML的
class属性需要写成className,否则会出现属性不生效/警告问题;且谷歌地图容器必须设置明确宽高,否则无法渲染也会引发报错。
- 属性书写不规范:React中HTML的
修复方案
第一步:修改GoogleMapsApi.js核心逻辑
用useEffect确保地图初始化只在组件挂载完成(DOM已渲染)后执行一次,修正事件绑定、属性书写问题:
import React, { useEffect, useRef } from "react"; import $ from "jquery"; const GoogleMapsApi = () => { // 用useRef保存地图实例,避免重渲染丢失 const mapRef = useRef(null); const directionsServiceRef = useRef(null); const directionsDisplayRef = useRef(null); const myLatLng = { lat: 51.5, lng: -0.1 }; // 组件挂载后初始化地图 useEffect(() => { // 先判断谷歌SDK是否加载完成 if (!window.google) { console.error("谷歌地图SDK未加载完成"); return; } const google = window.google; const mapOptions = { center: myLatLng, zoom: 7, mapTypeId: google.maps.MapTypeId.ROADMAP, }; // 此时DOM已经渲染,可以拿到节点 const map = new google.maps.Map( document.getElementById("googleMap"), mapOptions ); mapRef.current = map; directionsServiceRef.current = new google.maps.DirectionsService(); directionsDisplayRef.current = new google.maps.DirectionsRenderer(); directionsDisplayRef.current.setMap(map); }, []); // 空依赖数组,只执行一次 function calcRoute() { const google = window.google; if (!google || !directionsServiceRef.current || !directionsDisplayRef.current || !mapRef.current) return; const request = { origin: document.getElementById("from").value, destination: document.getElementById("to").value, travelMode: google.maps.TravelMode.DRIVING, unitSystem: google.maps.UnitSystem.METRIC, }; directionsServiceRef.current.route(request, function (result, status) { if (status === google.maps.DirectionsStatus.OK) { $("#output").html( "<div class='alert-info'>From: " + document.getElementById("from").value + ".<br />To: " + document.getElementById("to").value + ".<br /> Driving distance: " + result.routes[0].legs[0].distance.text + ".<br />Duration: " + result.routes[0].legs[0].duration.text + ".</div>" ); directionsDisplayRef.current.setDirections(result); } else { directionsDisplayRef.current.setDirections({ routes: [] }); mapRef.current.setCenter(myLatLng); $("#output").html( "<div class='alert-danger'>Could not retrieve driving distance.</div>" ); } }); } function getLocation() { const fromInput = document.getElementById("from"); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else { fromInput.value = "Geolocation is not supported by this browser."; } } function showPosition(position) { document.getElementById("from").value = position.coords.latitude + ", " + position.coords.longitude; } return ( <> <div className="App"> {/* 所有class改成className */} <div className="jumbotron"> <div className="container-fluid"> <h1>Distance between cities App.</h1> <p>Our app will help you calculate travelling distances.</p> <form className="form-horizontal"> <div className="form-group"> <label htmlFor="from" className="col-xs-2 control-label"> From: </label> <div className="col-xs-10"> <input type="text" id="from" placeholder="Origin" className="form-control" /> </div> </div> <div className="form-group"> <label htmlFor="to" className="col-xs-2 control-label"> To: </label> <div className="col-xs-10"> <input type="text" id="to" placeholder="Destination" className="form-control" /> </div> </div> </form> <div className="col-xs-offset-2 col-xs-10"> {/* 去掉onClick里的括号,传函数引用 */} <button className="btn btn-info btn-lg" onClick={getLocation}> Try It </button> <p id="demo"></p> </div> <div className="col-xs-offset-2 col-xs-10"> {/* 去掉onClick里的括号,传函数引用 */} <button className="btn btn-info btn-lg" onClick={calcRoute}> Submit </button> </div> </div> <div className="container-fluid"> {/* 给地图容器加自定义类,后续设置宽高 */} <div id="googleMap" className="google-map-container"></div> <div id="output"></div> </div> </div> </div> </> ); }; export default GoogleMapsApi;
第二步:给地图容器添加宽高样式
在App.css里添加如下样式:
.google-map-container { width: 100%; height: 400px; margin: 16px 0; }
内容的提问来源于stack exchange,提问作者mky
相关产品推荐
相关产品推荐

