react-google-maps-api icon indicating copy to clipboard operation
react-google-maps-api copied to clipboard

React Error: Maximum update depth exceeded after navigating back & forth with useJsApiLoader

Open alvalau opened this issue 1 year ago • 0 comments

Your Environment

os: mac

node --version: v21.1.0

react version: 18.2.0

nextjs version: 13.5.4

@react-google-maps/api version: 2.19.2

How does it behave?

I'm using NextJs, the useJsApiLoader is working just fine except if I use the browser's back & next button to navigate between 2 pages.

Steps to reproduce the error

  1. go to the page that has the integration of google map. (no error)
  2. use browser's back button to leave the page
  3. use browser's forward button to reenter the page. (has error : Maximum update depth exceeded)

Remarks

  • The error will not show if using router from next to navigate between pages
  • The error will not show if replacing useJsApiLoader with useLoadScript

Here is some what my component looks like:

const OurLocationMapView = ({ lng }: OurLocationMapViewProps) => {
  const [map, setMap] = useAtom(mapAtom);
  const [, setMapWrapper] = useAtom(mapWrapperAtom);
  const [maxZoom, setMaxZoom] = React.useState(15);
  const [center] = React.useState({
    lat: 22.308,
    lng: 114.178,
  });
  const { t } = useTranslation(lng, 'navbar');

  const { isLoaded, loadError } = useLoadScript({
    id: 'google-map-script',
    googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAP_API_KEY as string,
    language: lng,
  });

  const [stores] = useAtom(storesAtom);
  const [selectedStore, setSelectedStore] = useAtom(selectedStoreAtom);

  const onLoad = React.useCallback(function callback(map: any) {
    const bounds = new window.google.maps.LatLngBounds(center);
    map.fitBounds(bounds);

    setMap(map);

    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      setMaxZoom(20);
    }, 1000);
  }, []);

  const onUnmount = React.useCallback(function callback(map: any) {
    setMap(null);
    if (timer) clearTimeout(timer);
  }, []);

  if (!isLoaded || loadError) return null;

  return (
    <div
      id={'store-location-map'}
      ref={(ref) => setMapWrapper(ref)}
      className={'sticky top-0 h-[65svh] w-full xl:h-[100svh]'}
    >
      <GoogleMap
        mapContainerStyle={containerStyle}
        center={center}
        onLoad={onLoad}
        onUnmount={onUnmount}
        options={{
          styles: [...styleArray],
          clickableIcons: false,
          mapTypeControl: false,
          maxZoom,
        }}
      >
       {/* some markers & infowindow */}
    </div>
  )
}

I have tried removing the setters inside the onLoad handler, but the error still persist.

How should it behave correctly?

The error should not occur if using browser back & forward button.

alvalau avatar Nov 29 '23 05:11 alvalau