admin管理员组

文章数量:1328464

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?

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?

Share Improve this question edited Dec 14, 2019 at 18:48 norbitrial 15.2k10 gold badges39 silver badges64 bronze badges asked Dec 14, 2019 at 18:42 Michael LynchMichael Lynch 3,1594 gold badges39 silver badges70 bronze badges 3
  • 1 Does this answer your question? How to fix missing dependency warning when using useEffect React Hook? – MrUpsidown Commented Dec 14, 2019 at 18:46
  • Not really. If I add clearMarkers() into my useEffect() I get a different warning prompting me to add markers as a dependency and when I do that, I get the same infinite loop. I'm telling React to run the effect every time the markers change, and inside the effect, I change the markers by clearing them, so I understand why it's looping infinitely. I just don't know how else to acplish this. – Michael Lynch Commented Dec 14, 2019 at 19:05
  • You should consider to use @react-google-maps/api. It has <Market/> ponent and you can even create your own markers. Then you can just setMarkers to a new array with coords and the magic happens. – Christos Lytras Commented Dec 15, 2019 at 22:30
Add a ment  | 

2 Answers 2

Reset to default 4

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

本文标签: