New markers not added dynamically on google-maps-react (using useRef)

Viewed 358

I'm using google-maps-react with hook (react) .

But I have a question that I can't solve.

I am expecting a new marker to be created when HomContainer.tsx's onAddressSubmit function is executed.

But no new marker is created (no rendering ? )

function onAddressSubmit

The setCoordinates part executes normally and is stored in state.

However, after toMarker is activated, no new markers are created on the map.

Can you find a solution for this?

It also lacks a lot about using useEffect.

Can you point out the code?

Thank you for reading my code .

(I'm not good at English very well... Sorry !!! )

index.tsx

import { GoogleApiWrapper } from 'google-maps-react';
import HomeContainer from './HomeContainer';
import { MAPS_KEY } from '../../keys';

export default GoogleApiWrapper({
  apiKey: process.env.GOOGLE_API || MAPS_KEY
})(HomeContainer);

Container.tsx

import { useQuery } from '@apollo/react-hooks';
import React, { useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import { RouteComponentProps } from 'react-router-dom';
import HomePresenter from './HomePresenter';
import { geoCode } from '../../mapHelpers';
import { USER_PROFILE } from '../../sharedQueries';
import { UserProfile } from '../../types/api';

interface IState {
  isMenuOpen: boolean;
}

interface IProps extends RouteComponentProps {
  google: any;
}

const HomeContainer: React.SFC<IProps & IState> = ({ google }) => {
  const mapRef = useRef(null);
  let map: google.maps.Map;
  let userMarker: google.maps.Marker;
  let toMarker: google.maps.Marker;

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(handleGeoSuccess, handleGeoError);
  }, []);

  const { loading: getUserProfileLoading } = useQuery<UserProfile>(
    USER_PROFILE
  );

  const [isMenuOpen, setIsMenuOpen] = useState<IState["isMenuOpen"]>(false);
  const [coordinates, setCoordinates] = useState({
    lat: 0,
    lng: 0,
    toAddress: "",
    toLat: 0,
    toLng: 0
  });

  const { toAddress } = coordinates;

  const toggleMenu = () => {
    setIsMenuOpen(!isMenuOpen);
  };

  const handleGeoSuccess = (position: Position) => {
    const {
      coords: { latitude, longitude }
    } = position;
    setCoordinates({
      ...coordinates,
      lat: latitude,
      lng: longitude
    });
    loadMap(latitude, longitude);
  };

  const loadMap = (lat, lng) => {
    const maps = google.maps;
    const mapNode = ReactDOM.findDOMNode(mapRef.current);
    const mapConfig: google.maps.MapOptions = {
      center: {
        lat,
        lng
      },
      disableDefaultUI: true,
      minZoom: 8,
      zoom: 11
    };

    map = new maps.Map(mapNode, mapConfig);

    const userMarkerOptions: google.maps.MarkerOptions = {
      icon: {
        path: maps.SymbolPath.CIRCLE,
        scale: 7
      },
      position: {
        lat,
        lng
      }
    };
    userMarker = new maps.Marker(userMarkerOptions);
    userMarker.setMap(map);

    const watchOptions: PositionOptions = {
      enableHighAccuracy: true
    };

    navigator.geolocation.watchPosition(
      handleGeoWatchSuccess,
      handleGeoWatchError,
      watchOptions
    );
  };

  const handleGeoWatchSuccess = (position: Position) => {
    const {
      coords: { latitude, longitude }
    } = position;
    userMarker.setPosition({ lat: latitude, lng: longitude });
    map.panTo({ lat: latitude, lng: longitude });
  };

  const handleGeoWatchError = () => {
    console.log("Error watching you");
  };

  const handleGeoError = () => {
    console.log("No location");
  };

  const onInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const {
      target: { name, value }
    } = event;
    setCoordinates({
      ...coordinates,
      [name]: value
    } as any);
  };

  const onAddressSubmit = async () => {
    const maps = google.maps;
    const result = await geoCode(toAddress);
    if (result !== false) {
      const { lat, lng, formatted_address: formattedAddress } = result;
      setCoordinates({
        ...coordinates,
        toAddress: formattedAddress,
        toLat: lat,
        toLng: lng
      });
      if (toMarker) {
        toMarker.setMap(null);
      }
      const toMarkerOptions: google.maps.MarkerOptions = {
        position: {
          lat,
          lng
        }
      };
      toMarker = new maps.Marker(toMarkerOptions);
      toMarker.setMap(map);
    }
  };

  return (
    <HomePresenter
      toggleMenu={toggleMenu}
      isMenuOpen={isMenuOpen}
      getUserProfileLoading={getUserProfileLoading}
      mapRef={mapRef}
      toAddress={toAddress}
      onInputChange={onInputChange}
      onAddressSubmit={onAddressSubmit}
    />
  );
};

export default HomeContainer;

Presenter.tsx

import React from 'react';
import Helmet from 'react-helmet';
import Sidebar from 'react-sidebar';
import AddressBar from '../../Components/AddressBar';
import Button from '../../Components/Button';
import Menu from '../../Components/Menu';
import styled from '../../typed-components';

const Container = styled.div``;

const MenuButton = styled.button`
  appearance: none;
  padding: 10px;
  position: absolute;
  top: 10px;
  left: 10px;
  text-align: center;
  font-weight: 800;
  border: 0;
  cursor: pointer;
  font-size: 20px;
  transform: rotate(90deg);
  z-index: 2;
  background-color: transparent;
`;

const Map = styled.div`
  position: absolute;
  height: 100%;
  width: 100%;
`;

const ExtendedButton = styled(Button)`
  position: absolute;
  bottom: 50px;
  left: 0;
  right: 0;
  margin: auto;
  z-index: 10;
  height: auto;
  width: 80%;
`;

interface IProps {
  toggleMenu: () => void;
  isMenuOpen: boolean;
  getUserProfileLoading: boolean;
  mapRef: any;
  toAddress: string;
  onAddressSubmit: () => void;
  onInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

const HomePresenter: React.FC<IProps> = ({
  toggleMenu,
  isMenuOpen,
  getUserProfileLoading,
  mapRef,
  toAddress,
  onInputChange,
  onAddressSubmit
}) => {
  return (
    <Container>
      <Helmet>
        <title>HOME</title>
      </Helmet>
      <Sidebar
        sidebar={<Menu />}
        open={isMenuOpen}
        onSetOpen={toggleMenu}
        styles={{
          sidebar: {
            backgroundColor: "white",
            width: "80%",
            zIndex: "10"
          }
        }}
      >
        {!getUserProfileLoading && (
          <MenuButton onClick={toggleMenu}>|||</MenuButton>
        )}
        <AddressBar
          name={"toAddress"}
          onChange={onInputChange}
          value={toAddress}
          onBlur={null}
        />
        <ExtendedButton
          onClick={onAddressSubmit}
          disabled={toAddress === ""}
          value={"Pick Address"}
        />
        <Map ref={mapRef} />
      </Sidebar>
    </Container>
  );
};

export default HomePresenter;

0 Answers
Related