Новые маркеры не добавляются динамически в google-maps -реакции (используя useRef) - PullRequest
2 голосов
/ 02 марта 2020

Я использую google-maps -реагировать с крючком (реагировать).

Но у меня есть вопрос, который я не могу решить.

Я ожидаю, что новый маркер будет создается при выполнении функции onAddressSubmit в HomContainer.tsx.

Но новый маркер не создается (без рендеринга?)

функция onAddressSubmit

Часть setCoordinates выполняется нормально и сохраняется в состоянии.

Однако после активации toMarker на карте не создаются новые маркеры.

Можете ли вы найти решение для этого?

В нем также много не хватает использования useEffect.

Можете ли вы указать код?

Спасибо за чтение моего кода.

(я плохо разбираюсь в английском sh очень хорошо ... извините !!!)

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;

...