1

I'm using Next.js version 12.3.1 and React.js 18.2.0. When I select point A and point B the direction service and direction renderer gets called and the map prints the direction with the markers. But when I change points A and B the map prints a new direction but the very first direction/line stays on the map. How do I fix the issue? Here is the Map functions file:

import React, { useCallback, useState } from "react";
import CustomGoogleMap from "@components/core/CustomGoogleMap";
import { Box } from "@mui/material";
import { anyObjectType } from "@services/types";
import MapAPI from "@services/api/map";
import { CreateBookingActions } from "@services/constants";
import { useCreateBookingContext } from "@contexts/CreateBookingContext";

const BookingMap: React.FC<BookingMapProps> = ({
  memoizedloadingPoint,
  memoizedunloadingPoint,
  memoizedwaypointsList,
  setToast,
  setLoadingPoint,
  setUnLoadingPoint,
}) => {
  const cbCtx = useCreateBookingContext();
  const { state, dispatch } = cbCtx;
  const { waypointsList } = state;
  const [call, setCall] = useState(false);
  const handleLoadingPointDragLocation = useCallback(
    async (lat: number, lng: number) => {
      if (lat && lng) {
        const query = {
          latlng: `${lat},${lng}`,
        };
        const { response, error }: any = await MapAPI.onDrag(query);
        if (response) {
          setLoadingPoint({
            ...response.data.data,
          });
        } else {
          setToast("Somthing went wrong", "error");
        }
      }
    },
    []
  );

  const handleUnLoadingPointDragLocation = useCallback(
    async (lat: number, lng: number) => {
      if (lat && lng) {
        const query = {
          latlng: `${lat},${lng}`,
        };
        const { response, error }: any = await MapAPI.onDrag(query);
        if (response) {
          setUnLoadingPoint({
            ...response.data.data,
          });
        } else {
          setToast("Somthing went wrong", "error");
        }
      }
    },
    []
  );

  const setWaypointsList = (val: any[]) => {
    dispatch({
      type: CreateBookingActions.SET_WAYPOINT_LIST,
      payload: val,
    });
  };

  const handleStopageDragLocation = useCallback(
    async (lat: number, lng: number, index: number) => {
      if (lat && lng) {
        const query = {
          latlng: `${lat},${lng}`,
        };
        const { response, error }: any = await MapAPI.onDrag(query);
        if (response) {
          const updatedWaypoints = JSON.parse(JSON.stringify(waypointsList));
          updatedWaypoints.splice(index, 1, { ...response.data.data });
          setWaypointsList([...updatedWaypoints]);
          setCall(true);
        } else {
          setToast("Somthing went wrong", "error");
        }
      }
    },
    []
  );

  return (
    <Box sx={{ height: "420px" }}>
      <CustomGoogleMap
        call={call}
        setCall={setCall}
        loadingP={memoizedloadingPoint}
        unloadingP={memoizedunloadingPoint}
        waypointsList2={memoizedwaypointsList}
        handleLoadingPointDragLocation={handleLoadingPointDragLocation}
        handleUnLoadingPointDragLocation={handleUnLoadingPointDragLocation}
        handleStopageDragLocation={handleStopageDragLocation}
      />
    </Box>
  );
};

export default BookingMap;

interface BookingMapProps {
  memoizedloadingPoint: anyObjectType;
  memoizedunloadingPoint: anyObjectType;
  memoizedwaypointsList: any[];
  setToast: (a: string, b: string) => void;
  setLoadingPoint: (a: anyObjectType) => void;
  setUnLoadingPoint: (a: anyObjectType) => void;
}

Here is the google map file:

import React, { useEffect, useState, memo } from "react";
import {
  GoogleMap,
  MarkerF,
  DirectionsRenderer,
  DirectionsService,
  InfoWindow,
  useLoadScript,
  LoadScriptNext,
} from "@react-google-maps/api";
import LoadingMarker from "../SvgIcons/loading-marker.svg";
import UnLoadingMarker from "../SvgIcons/unloading-marker.svg";
import StoppageIcon from "../SvgIcons/stopageIcon.svg";
import { CircularProgress } from "@mui/material";
import { Box } from "@mui/system";
import { isEmptyArray } from "@services/utils";
import { anyObjectType, Dispatcher } from "@services/types";

const containerStyle = {
  width: "100%",
  height: "100%",
};

const center = {
  lat: 23.810331,
  lng: 90.412521,
};

interface CustomLatLong {
  latitude: number;
  longitude: number;
  textEn: string;
}

type CustomDirectionsWaypoint = google.maps.DirectionsWaypoint & CustomLatLong;

interface CustomGoogleMapProps {
  call: Boolean;
  setCall: Dispatcher<boolean>;
  handleStopageDragLocation?: (a: number, b: number, c: number) => void;
  handleLoadingPointDragLocation?: (a: number, b: number) => void;
  handleUnLoadingPointDragLocation?: (a: number, b: number) => void;
  waypointsList2: CustomDirectionsWaypoint[];
  loadingP: anyObjectType;
  unloadingP: anyObjectType;
  isAddressModal?: Boolean;
}

const CustomGoogleMap: React.FC<CustomGoogleMapProps> = (props) => {
  const {
    call,
    setCall,
    loadingP,
    unloadingP,
    waypointsList2,
    handleLoadingPointDragLocation,
    handleUnLoadingPointDragLocation,
    handleStopageDragLocation,
    isAddressModal = false,
  } = props;

  // const { isLoaded, loadError } = useLoadScript({
  //   googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!,
  // });

  const [infoBox, setInfoWindow] = useState({
    position: {
      lat: 0,
      lng: 0,
    },
    info: "",
  });

  const [directions, setDirections] = useState(null);
  console.log("point:", loadingP, unloadingP);

  useEffect(() => {
    if (loadingP.latitude && unloadingP.latitude) {
      setCall(true);
    }
  }, [loadingP.latitude, unloadingP.latitude]);

  const directionsCallback = (response: any) => {
    if (response !== null) {
      console.log("directionsCallback called");
      if (response.status === "OK") {
        setCall(false);
        setDirections(response);
      }
    }
  };

  const getDirectionRender = () => {
    return (
      <DirectionsService
        options={{
          destination: {
            lat: unloadingP.latitude,
            lng: unloadingP.longitude,
          },
          origin: {
            lat: loadingP.latitude,
            lng: loadingP.longitude,
          },
          travelMode: google.maps.TravelMode.DRIVING,
          waypoints: waypointsList2.map(({ latitude, longitude }) => {
            return {
              location: {
                lat: latitude,
                lng: longitude,
              }.toString(),
              stopover: false,
            };
          }),
        }}
        callback={directionsCallback}
      />
    );
  };

  // if (loadError) {
  //   return <div>Map cannot be loaded right now, sorry.</div>;
  // }

  const renderMap = () => {
    return (
      <LoadScriptNext
        googleMapsApiKey={process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!}
      >
        <GoogleMap
          mapContainerStyle={containerStyle}
          center={
            loadingP.latitude
              ? {
                  lat: loadingP.latitude,
                  lng: loadingP.longitude,
                }
              : center
          }
          zoom={10}
          onClick={({ latLng }) => {
            isAddressModal &&
              handleLoadingPointDragLocation &&
              handleLoadingPointDragLocation(latLng!.lat(), latLng!.lng());
          }}
        >
          {loadingP.latitude &&
            unloadingP.latitude &&
            call &&
            getDirectionRender()}
          {directions && (
            <DirectionsRenderer
              options={{
                directions: directions,
                suppressMarkers: true,
              }}
            />
          )}

          {infoBox.position.lat && (
            <InfoWindow
              // options={infoBoxOptions}
              position={infoBox.position}
              onCloseClick={() =>
                setInfoWindow({
                  position: {
                    lat: 0,
                    lng: 0,
                  },
                  info: "",
                })
              }
            >
              <p> {infoBox.info}</p>
            </InfoWindow>
          )}

          <MarkerF
            key={loadingP.latitude}
            draggable
            onDragEnd={({ latLng }) => {
              handleLoadingPointDragLocation &&
                handleLoadingPointDragLocation(latLng!.lat(), latLng!.lng());
            }}
            position={{ lat: loadingP.latitude, lng: loadingP.longitude }}
            icon={LoadingMarker}
            onClick={() =>
              setInfoWindow({
                ...infoBox,
                position: {
                  lat: loadingP.latitude,
                  lng: loadingP.longitude,
                },
                info: loadingP.textEn,
              })
            }
          />
          <MarkerF
            key={unloadingP.latitude}
            draggable
            onDragEnd={({ latLng }) => {
              handleUnLoadingPointDragLocation &&
                handleUnLoadingPointDragLocation(latLng!.lat(), latLng!.lng());
            }}
            position={{
              lat: unloadingP.latitude,
              lng: unloadingP.longitude,
            }}
            icon={UnLoadingMarker}
            onClick={() =>
              setInfoWindow({
                ...infoBox,
                position: {
                  lat: unloadingP.latitude,
                  lng: unloadingP.longitude,
                },
                info: unloadingP.textEn,
              })
            }
          />
          {!isEmptyArray(waypointsList2) &&
            waypointsList2.map((item, index) => {
              return (
                <MarkerF
                  key={index}
                  draggable
                  visible
                  onDragEnd={({ latLng }) => {
                    handleStopageDragLocation &&
                      handleStopageDragLocation(
                        latLng!.lat(),
                        latLng!.lng(),
                        index
                      );
                  }}
                  position={{
                    lat: item.latitude,
                    lng: item.longitude,
                  }}
                  icon={StoppageIcon}
                  onClick={() =>
                    setInfoWindow({
                      ...infoBox,
                      position: {
                        lat: item.latitude,
                        lng: item.longitude,
                      },
                      info: item.textEn,
                    })
                  }
                />
              );
            })}
        </GoogleMap>
      </LoadScriptNext>
    );
  };
  return renderMap();
};

export default memo(CustomGoogleMap);

react google maps

Kamrul Islam
  • 255
  • 4
  • 15

0 Answers0