You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在React中接入Google Maps API实现两点路线计算相关问题求助

报错原因&解决方案

核心报错原因

    1. DOM渲染时机不匹配:你在组件顶层直接执行地图初始化、查询DOM元素的逻辑,此时组件的JSX还没渲染到真实DOM上,document.getElementById("googleMap")、document.getElementById("from")拿到的都是null,直接调用相关API必然报错。
    1. 谷歌SDK加载时机问题:直接在组件顶层声明const google = window.google,如果谷歌地图SDK还没加载完成,window.google是undefined,调用google.maps相关API直接报错。
    1. 事件绑定错误:你写的onClick={getLocation()}、onClick={calcRoute()}是组件渲染时直接执行函数,不是点击后才执行,此时DOM还没生成,直接触发报错。
    1. 重复初始化地图:函数组件每次重渲染都会执行顶层代码,会反复创建地图实例,引发冲突报错。
    1. 属性书写不规范:React中HTML的class属性需要写成className,否则会出现属性不生效/警告问题;且谷歌地图容器必须设置明确宽高,否则无法渲染也会引发报错。

修复方案

第一步:修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:24:07