我正在使用 React 和
@react-google-maps/api
开发一个送货应用程序。我有一个地图组件,它使用自定义图标显示送货人员的位置。但是,我遇到了一个问题,即当送货人员的状态发生变化(例如,从“正在送货”到“已送货”)时,标记的图标不会动态更新。
这是我的地图组件的简化版本:
import React from 'react';
import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';
const mapContainerStyle = {
width: '800px',
height: '600px',
};
const center = {
lat: -34.397,
lng: 150.644,
};
const deliveryWorkerIcon = "https://www.citypng.com/public/uploads/large/701751694974714k04h1qhze9qoibj5zsdeldgmudwiygsfhulvidozwie8c3x74fcxvb3skcj0yqfnr2xehmarxrjwct6xtqgpbryyi5giatccgmjb.png";
const MapComponent = () => {
return (
<LoadScript googleMapsApiKey="">
<GoogleMap
mapContainerStyle={mapContainerStyle}
center={center}
zoom={10}
>
<Marker
position={center}
icon={{
url: deliveryWorkerIcon,
scaledSize: new window.google.maps.Size(50, 50),
}}
/>
</GoogleMap>
</LoadScript>
);
};
export default MapComponent;
当送货员的状态更新时,标记应该会发生变化,但图标保持不变。我尝试使用
useState
根据工作人员的状态动态更新 deliveryWorkerIcon
URL,但标记不会使用新图标重新渲染。
如何确保标记图标动态更新以响应组件中的状态或道具更改?
从您提供的代码片段中,我看不到以下部分:
要动态更改标记,您需要一种方法来侦听状态更改,然后相应地更新图标。如果您包含使用
useState
的代码部分,将会很有帮助,这样我们也可以检查任何潜在的问题。
在我的例子中,使用相同的库
(@react-google-maps/api)
,我使用useEffect
钩子根据过期时间动态更新标记图标(我将其作为属性包含在我的标记对象中:expirationTime
)。在效果内部,我设置了一个间隔来定期检查是否有任何标记的 expirationTime
已通过。如果是这样,图标将更新为自定义图标。
您可以在此处查看示例结果。
下面是我完整的地图组件供您检查。请记住,如何实现状态更改侦听器的具体细节将取决于您的应用程序设置,因此请将此视为指南。
import React, { useState, useRef, useCallback, useEffect } from "react";
import { GoogleMap, useLoadScript, Marker } from "@react-google-maps/api";
const mapContainerStyle = {
width: "100wh",
height: "100vh",
};
const center = {
lat: -37.397,
lng: 150.644,
};
export default function Map() {
const { isLoaded, loadError } = useLoadScript({
googleMapsApiKey: 'YOUR_API_KEY',
});
const [markers, setMarkers] = useState([]);
const mapRef = useRef();
// Add a marker to the map at the clicked location
const onMapClick = useCallback((event) => {
setMarkers((current) => [
...current,
{
lat: event.latLng.lat(),
lng: event.latLng.lng(),
customIcon: 'https://www.citypng.com/public/uploads/large/701751694974714k04h1qhze9qoibj5zsdeldgmudwiygsfhulvidozwie8c3x74fcxvb3skcj0yqfnr2xehmarxrjwct6xtqgpbryyi5giatccgmjb.png',
expirationTime: new Date(Date.now() + 5000), // Expire the default icon after 5 seconds
}
]);
}, []);
const onLoad = useCallback((map) => {
mapRef.current = map;
}, []);
useEffect(() => {
const intervalId = setInterval(() => {
setMarkers((markers) => markers.map((marker) => {
// If marker is expired, change its icon to the custom icon
if (new Date() > marker.expirationTime) {
return { ...marker, icon: marker.customIcon };
} else {
return marker;
}
}));
}, 1000); // Checks if the expirationTime passes every 1 second
return () => clearInterval(intervalId);
}, []);
if (loadError) return "Error loading maps";
if (!isLoaded) return "Loading Maps";
return (
<GoogleMap
mapContainerStyle={mapContainerStyle}
zoom={8}
center={center}
onClick={onMapClick}
onLoad={onLoad}
>
{markers.map((marker, index) => (
<Marker
key={index}
position={{ lat: marker.lat, lng: marker.lng }}
icon={{ url: marker.icon, scaledSize: new window.google.maps.Size(50, 50), }}
/>
))}
</GoogleMap>
);
}