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)'.
问题分析
- 当前位置初始状态错误:
currentLatitude和currentLongitude初始值设为Number构造函数,而非数值类型,导致初始状态为函数类型,不符合Marker对经纬度的类型要求。 - 诊所经纬度处理逻辑错误:
clinic.parseInt(longitude)是错误调用方式,正确转换应为parseInt(clinic.longitude)或Number(clinic.longitude);且未校验API返回的经纬度是否为有效数值(可能为字符串或undefined)。 - 缺失无效数据过滤:未过滤经纬度缺失或无效的诊所条目,导致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
相关产品推荐
相关产品推荐

