I have a React app that displays a map with some markers on it. The map markers are refreshed by clicking a button that fetches new locations from the Google Maps API. I want to remove the previous location markers from the map on each refresh.
import React, { useEffect, useState } from 'react';
function Map(props) {
const [markers, setMarkers] = useState();
function clearMarkers() {
for(let i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
}
useEffect(() => {
clearMarkers();
if(props.locations.length) {
const googleMarkers = [];
for(let i = 0; i < props.locations.length; i++) {
const marker = new window.google.maps.Marker({...});
googleMarkers.push(marker);
}
setMarkers(googleMarkers);
}
}, [props.locations, props.map]);
}
I have it working, but I am getting a warning from React.
React Hook useEffect has a missing dependency: 'clearMarkers'. Either include it or remove the dependency array
I need the dependency array, so the markers only refresh when there are new props.locations, but when I include it in the dependency array, I get an infinite loop.
How can I clear the markers off the map before adding new ones without React throwing a warning? Or should I not be concerned with the warning?
You could consider to store markers via mutable ref object (as described here):
const prevMarkersRef = useRef([]);
to distinguish previous markers. And then clear previous markers once locations prop gets updated:
useEffect(() => {
//clear prev markers
clearMarkers(prevMarkersRef.current);
//render markers
for (let loc of props.locations) {
const marker = createMarker({ lat: loc.lat, lng: loc.lng }, map);
prevMarkersRef.current.push(marker);
}
});
where
function createMarker(position, map) {
return new window.google.maps.Marker({
position: position,
map: map
});
}
function clearMarkers(markers) {
for (let m of markers) {
m.setMap(null);
}
}
Here is a demo
You can try and memoize your clearMarkers function and add it to the dependency array of useEffect using useCallback
As your code reads you are creating a new function on each render so the effect is triggered every time if you add the function to the dependency array
this should work
const cb = useCallback(function clearMarkers() {
for(let i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
}, [markers.length]);
useEffect(() => {
cb();
if (props.locations.length) {
const googleMarkers = [];
for (let i = 0; i < props.locations.length; i++) {
const marker = `marker #${i}`;
googleMarkers.push(marker);
}
setMarkers(googleMarkers);
}
}, [props.locations, cb]);
but you can also just add the clearing loop inside useEffect and add the markers.length to the dependency array
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With