我正在使用 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;