JustFly1984 / react-google-maps-api

React Google Maps API
MIT License
1.75k stars 426 forks source link

https://react-google-maps-api-docs.netlify.app/#directionsrenderer #3257

Open dannyng1988 opened 1 year ago

dannyng1988 commented 1 year ago

Please check out the directionsrenderer code example. The map keeps refreshing when you choose driving route.

https://react-google-maps-api-docs.netlify.app/#directionsrenderer

theer1k commented 1 year ago

I had the same problem. I was able to fix in my implementation by splitting in two components and using memo avoiding some infinite update state/re-rendering happening on the GoogleMap component, here is the code:

import { DirectionsRenderer, GoogleMap } from '@react-google-maps/api';
import React, { memo, useState } from 'react';

export interface GoogleMapsDirectionsProps {
  origin: {
    lat: number;
    lng: number;
  };
  destination: {
    lat: number;
    lng: number;
  };
}

export const GoogleMapsDirections = memo(
  ({ origin, destination }: GoogleMapsDirectionsProps) => {
    const DirectionsService = new google.maps.DirectionsService();

    return (
      <GoogleMap
        id="google-map"
        mapContainerStyle={{
          borderRadius: '0.625rem',
          height: '100%',
          width: '100%',
        }}
        center={{
          lat: destination.lat,
          lng: destination.lng,
        }}
        zoom={10}
      >
        <DirectionsRendererWrapper
          origin={origin}
          destination={destination}
          directionsService={DirectionsService}
        />
      </GoogleMap>
    );
  },
);

export interface DirectionsRendererWrapperProps {
  origin: {
    lat: number;
    lng: number;
  };
  destination: {
    lat: number;
    lng: number;
  };
  directionsService: google.maps.DirectionsService;
}

const DirectionsRendererWrapper = memo(
  ({
    destination,
    origin,
    directionsService,
  }: DirectionsRendererWrapperProps) => {
    const [directions, setDirections] =
      useState<google.maps.DirectionsResult | null>(null);

    React.useEffect(() => {
      directionsService.route(
        {
          origin,
          destination,
          travelMode: google.maps.TravelMode.DRIVING,
        },
        (result, status) => {
          if (status === google.maps.DirectionsStatus.OK) {
            setDirections(result);
          } else {
            console.error(`error fetching directions ${result}`);
          }
        },
      );
    }, [origin, destination, directionsService]);

    if (!directions) {
      return null;
    }

    return (
      <DirectionsRenderer
        options={{
          directions: directions,
        }}
      />
    );
  },
);

🍻

theer1k commented 1 year ago

Also reported on https://github.com/JustFly1984/react-google-maps-api/issues/3256

JustFly1984 commented 1 year ago

mapContainerStyle, center and DirectionsService should be wrapped in useMemo!

options for DirectionsRenderer should be wrapped into useMemo too!

JustFly1984 commented 1 year ago

also save component into intermediate const before passing it into React.memo