1

I'm getting markers when location is entered by the user, and the markers list is then provided to the Google Maps component. Since I don't want the map to re-render everytime, I have memoized it. It only re-renders when the markers props changes. But when markers changes, I get the following warning:

Warning: The final argument passed to useMemo changed size between renders. The order and size of this array must remain constant.

I followed answers in the other posts, and none worked for me. What am I doing wrong?

const [plants, setPlants] = useState([
    {
      name: "Plant 1",
      id: uuidv4(),
      location: "",
      coords: {},
      country: "",
      isOffshore: false,
    },
  ]);

  const isObjectEmpty = (obj) => {
    for (var i in obj) return false;
    return true;
  };

  const getMarkers = () => {
    var temp = [];
    for (var i = 0; i < plants.length; i++)
      if (!isObjectEmpty(plants[i].coords)) temp.push(plants[i].coords);
    return temp;
  };

  const markers = useMemo(
    () => getMarkers(),
    [...plants.map((item) => item.coords)]
  );

My map component:

const MapContainer = React.memo((props) => {
  const [map, setMap] = useState();
  const [center, setCenter] = useState({ lat: 59.913, lng: 10.75 });
  var bounds = new props.google.maps.LatLngBounds();

  const setMapObj = (mapProps, map) => {
    setMap(map);
  };

  useDeepCompareEffect(() => {
    console.log(props.markers);
    if (props.markers.length < 1) return;
    setCenter(props.markers[props.markers.length - 1]);
    //this is to zoom out the map by bit;
    //we provide bounds but not the marker
    // if (props.markers.length === 1) {
    //   bounds.extend(
    //     new props.google.maps.LatLng(props.markers[0].lat, props.markers[0].lng)
    //   );
    //   bounds.extend(
    //     new props.google.maps.LatLng(
    //       props.markers[0].lat - 1,
    //       props.markers[0].lng - 1
    //     )
    //   );
    //   map && map.fitBounds(bounds);
    //   return;
    // }
    // for (var i = 0; i < props.markers.length; i++) {
    //   bounds.extend(
    //     new props.google.maps.LatLng(props.markers[i].lat, props.markers[i].lng)
    //   );
    // }
    // if (map) {
    //   map.fitBounds(bounds);
    // }
  }, [props.markers, map]);

  return (
    <div className={props.className}>
      <Map
        google={props.google}
        style={{ borderRadius: "10px" }}
        center={center}
        initialCenter={{ lat: 59.913, lng: 10.75 }}
        onReady={setMapObj}
        zoom={7}
      >
        {props.markers.map((item, index) => {
          if (item.lat && item.lng)
            return (
              <Marker key={index} position={{ lat: item.lat, lng: item.lng }} />
            );
        })}
      </Map>
    </div>
  );
});

U. Watt
  • 533
  • 1
  • 5
  • 27

1 Answers1

2
 const markers = useMemo(
    () => getMarkers(),
    [...plants.map((item) => item.coords)]
  );

If the coordinates are for example [[1,2],[3,4],[4,5]], you are actually passing [[1,2],[3,4],[4,5]] as dependency.

You should probably just use

 const markers = useMemo(
    () => getMarkers(),
    [plants]
  );
Someone Special
  • 12,479
  • 7
  • 45
  • 76