2

我正在使用 google-maps-react 和 hook (react) 。

但是我有一个我无法解决的问题。

我期望在执行 HomContainer.tsx 的 onAddressSubmit 函数时创建一个新标记。

但是没有创建新的标记(没有渲染?)

函数地址提交

setCoordinates 部分正常执行并存储在 state 中。

但是,激活 toMarker 后,地图上不会创建新的标记。

你能找到解决方案吗?

它也缺少很多关于使用 useEffect 的内容。

你能指出代码吗?

感谢您阅读我的代码。

(我英语不太好……对不起!!!)

索引.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);

容器.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;

演示者.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;

4

0 回答 0