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

React Google Maps Marker坐标类型不匹配错误求解决方案

地图应用Marker经纬度绑定错误解决方案

错误场景

开发地图应用标记用户位置与API返回的诊所位置时,出现类型不匹配错误,错误信息如下:

No overload matches this call.
Overload 1 of 2, '(props: MarkerProps | Readonly): Marker', gave the following error.
The type 'number | undefined' is not assignable to the type 'number | (() => number)'.
The type 'undefined' is not assignable to the type 'number | (() => number)'.
Overload 2 of 2, '(props: MarkerProps, context: any): Marker', gave the following error.
The type 'undefined' is not assignable to the type 'number | (() => number)'.

问题分析

  1. 当前位置初始状态错误:currentLatitude和currentLongitude初始值设为Number构造函数,而非数值类型,导致初始状态为函数类型,不符合Marker对经纬度的类型要求。
  2. 诊所经纬度处理逻辑错误:clinic.parseInt(longitude)是错误调用方式,正确转换应为parseInt(clinic.longitude)或Number(clinic.longitude);且未校验API返回的经纬度是否为有效数值(可能为字符串或undefined)。
  3. 缺失无效数据过滤:未过滤经纬度缺失或无效的诊所条目,导致Marker接收到undefined值。

解决方案

步骤1:修正当前位置初始状态

明确当前位置的类型,初始值设为undefined或默认数值:

const [currentLatitude, setCurrentLatitude] = useState<number | undefined>(undefined);
const [currentLongitude, setCurrentLongitude] = useState<number | undefined>(undefined);

步骤2:修复诊所经纬度转换逻辑

过滤无效诊所数据,正确转换经纬度为数值:

{clinicList
  .filter(clinic => clinic.latitude != null && clinic.longitude != null)
  .map(clinic => {
    const lat = Number(clinic.latitude);
    const lng = Number(clinic.longitude);
    if (isNaN(lat) || isNaN(lng)) return null;
    return <Marker key={clinic.id /* 使用诊所唯一标识作为key */} position={{ lat, lng }} />;
  })}

步骤3:优化地图加载逻辑

避免在未获取用户位置时渲染无效地图,或设置默认中心坐标:

// 设置默认中心坐标,避免初始状态无效
const center = {
  lat: currentLatitude || 40.7128, // 示例:纽约纬度
  lng: currentLongitude || -74.0060 // 示例:纽约经度
};

// 或仅在获取到用户位置后渲染地图
return isLoaded && currentLatitude != null && currentLongitude != null ? (
  // 地图渲染内容
) : <Loader />;

完整修改后的代码

import React, { useState, useEffect, useCallback } from 'react'
import { getClinic } from '../../api/drupalAPI'
import { Clinic } from '@icofcv/common';
import Loader from '../spinner/Loader';
import { GoogleMap, useJsApiLoader, Marker } from '@react-google-maps/api'

export const PruevaClinicLocator = () => {
    const [clinicList, setClinicList] = useState<Clinic[]>([]);
    // 修正初始状态类型
    const [currentLatitude, setCurrentLatitude] = useState<number | undefined>(undefined);
    const [currentLongitude, setCurrentLongitude] = useState<number | undefined>(undefined);

    const { isLoaded } = useJsApiLoader({
        id: 'google-map-script',
        googleMapsApiKey: "AIzaSyB17U-TaHiXF-egDyrrCT_kejxz5ckXDNA"
    })
    
    const [map, setMap] = React.useState<google.maps.Map | null>(null)
    // 修正onLoad依赖,添加当前位置参数
    const onLoad = useCallback(function callback(mapInstance: google.maps.Map) {
        if (currentLatitude == null || currentLongitude == null) return;
        const bounds = new window.google.maps.LatLngBounds({ lat: currentLatitude, lng: currentLongitude });
        mapInstance.fitBounds(bounds);
        setMap(mapInstance)
    }, [currentLatitude, currentLongitude])
    
    const onUnmount = useCallback(function callback() {
        setMap(null)
    }, [])

    const containerStyle = {
        width: "100vw",
        height: "100vh"
    };

    const center = {
        lat: currentLatitude || 40.7128, // 默认纬度
        lng: currentLongitude || -74.0060 // 默认经度
    };

    const fetchClinicList = async () => {
        try {
            const response = await getClinic();
            console.log(response);
            setClinicList(response);
        } catch (error) {
            console.error(error);
            throw error;
        }
    }

    useEffect(() => {
        navigator.geolocation.getCurrentPosition((position) => {
            setCurrentLatitude(position.coords.latitude);
            setCurrentLongitude(position.coords.longitude);
            fetchClinicList(); 
        }, (error) => {
            // 添加定位失败处理
            console.error('定位失败:', error);
            fetchClinicList(); // 定位失败仍加载诊所数据
        });
    }, []);
   
    return isLoaded ? ( 
        <div>
            <GoogleMap 
                zoom={10} 
                mapContainerStyle={containerStyle}
                center={center}
                onLoad={onLoad}
                onUnmount={onUnmount}
            >
                {/* 仅在获取到当前位置时渲染用户Marker */}
                {currentLatitude != null && currentLongitude != null && (
                    <Marker position={{ lat: currentLatitude, lng: currentLongitude }} />   
                )}
                {/* 过滤并转换有效诊所数据 */}
                {clinicList
                    .filter(clinic => clinic.latitude != null && clinic.longitude != null)
                    .map(clinic => {
                        const lat = Number(clinic.latitude);
                        const lng = Number(clinic.longitude);
                        if (isNaN(lat) || isNaN(lng)) return null;
                        // 替换为诊所的唯一标识字段
                        return <Marker key={clinic.id} position={{ lat, lng }} />;
                    })}     
            </GoogleMap> 
        </div>
    ) : <Loader />;
}

额外说明

  • 确保Clinic类型中的latitude和longitude字段定义正确,若为可选字段必须在渲染前校验非空。
  • 为每个Marker添加唯一key属性,避免React列表渲染警告。
  • 添加定位失败处理逻辑,保证即使无法获取用户位置,也能加载诊所数据。

内容的提问来源于stack exchange,提问作者cuencadelrio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:20:27