提问人:barisdevjs 提问时间:11/17/2023 更新时间:11/17/2023 访问量:12
setMap:不是 Map 的实例;而不是 StreetViewPanorama @react-google-maps/api 的实例未显示 Infobox 组件
setMap: not an instance of Map; and not an instance of StreetViewPanorama @react-google-maps/api is not showing the Infobox component
问:
我有一个这样的父组件,其中包括 Google Map 的切换逻辑。 目前,@react-google-maps/api 没有显示切换地图的 Infobox 组件。我阅读了所有关于此的帖子,但我无法找到适合我的情况的解决方案。任何帮助将不胜感激。
import React, { useEffect, useLayoutEffect } from 'react';
import './InsPage.scss';
import { useLocation } from 'react-router-dom';
import { motion } from 'framer-motion';
import { pageTransition, pageVariants } from '../../utils/utils';
import useSideMenu from 'stores/sideMenu/sideMenu';
import Side from 'components/Side/Side';
import InsMap from 'components/InsMap/InsMap';
import usePublicInstitution from 'components/Institution/usePublicInstitution';
import { useInsStore } from 'store/insStore';
import Button from 'components/Button/Button';
const InsPage = () => {
const location = useLocation();
const { city, country, clearStore, setService, mapShow, setMapShow, sideShow } = useInsStore();
const { closeSideMenu } = useSideMenu();
const btnHandler = () => {
setMapShow(!mapShow);
};
const { institutions, markers, serviceCall } = usePublicInstitution({
type: undefined,
employee: undefined,
meridian: undefined,
parallel: undefined,
cityCode: city.code,
networkCodes: [],
distance: undefined,
country: country.code,
selectedMarker: null
});
useLayoutEffect(() => {
setService(serviceCall);
}, [serviceCall]);
useEffect(() => {
closeSideMenu();
return () => {
clearStore();
};
}, [location]);
return (
<motion.div
variants={pageVariants}
transition={pageTransition}
className="InsPage"
data-testid="InsPage"
id="InsPage"
>
<div style={{ backgroundColor: '#f8f8fa' }} className="flex">
{sideShow && <Side ins={institutions} />}
{mapShow === true && <InsMap markers={[...markers]} />}
<Button
style={{ fontSize: 'small' }}
className="Secondary-Thin"
id="MapButton"
onClick={btnHandler}
label={mapShow ? 'Liste Görünümü' : 'Harita Görünümü'}
></Button>
</div>
</motion.div>
);
};
export default InsPage;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
我的问题是,当我第一次单击任何标记时,它会向我显示 Infobox 组件。但是,随后我切换列表与地图,然后单击任何标记,我收到此错误:InvalidValueError:setMap:不是Map的实例;而不是 StreetViewPanorama 的实例
InsMap 是这样的:
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { GoogleMap, InfoBox, LoadScript, Marker } from '@react-google-maps/api';
import InfoBoxComponent from '@react-google-maps/api/dist/components/addons/InfoBox';
import './InsMap.scss';
import Pin from '../../assets/png/pin.png';
import doctorPin from '../../assets/png/doctor-pin.png';
import ttmPin from '../../assets/png/ttm-pin.png';
import hospitalPin from '../../assets/png/hastane-pin.png';
import eczanePin from '../../assets/png/eczane-pin.png';
import { mapContainerStyle, mapOptions } from '../../pages/InstitutionPublicPage/utils';
import { getGmapsKeys } from 'providers/providers';
import { TInstitution, TStartPoint } from 'commonTypes/commonTypes';
import { useInsStore } from 'store/insStore';
import { Mkr } from 'pages/InstitutionPage/InstitutionPage';
import InsInfoCard from 'components/InsInfoCard/InsInfoCard';
import { useInsList, useMarker } from 'store/store';
import MapNav from 'components/MapNav/MapNav';
export interface InsMapProps {
markers: Mkr[];
}
const InsMap = ({ markers }: InsMapProps) => {
const infoBoxRef = useRef<InfoBoxComponent>(null);
const { markerId } = useMarker();
const [isInfoBoxOpen, setIsInfoBoxOpen] = useState<boolean>(false);
const [responseMarkers, setResponseMarkers] = useState<Mkr[]>([]);
const [selectedMarker, setSelectedMarker] = useState<Mkr | null>(null);
const [map, setMap] = useState<google.maps.Map<Element>>();
const mapRef = useRef<google.maps.Map<Element>>();
const { city, district, insType, country, searchStr } = useInsStore();
const { ins } = useInsList();
const [center, setCenter] = useState<TStartPoint>({
lat: 0,
lng: 0
});
const onLoadMap = useCallback(
(mapFromLib: google.maps.Map<Element>) => {
mapRef.current = mapFromLib;
setMap(mapFromLib);
},
[map]
);
const convertToNumber = (point: TStartPoint): TStartPoint => {
const n: TStartPoint = {
lat: parseFloat(String(point.lat)),
lng: parseFloat(String(point.lng))
};
return n;
};
const onMarkerClick = useCallback(
(event) => {
setSelectedMarker(event);
setIsInfoBoxOpen(true);
event && setCenter(event.position);
},
[map]
);
const markerType = (obj: any) => {
switch (obj.typeId) {
case '1001':
return hospitalPin;
case '1002':
return eczanePin;
case '1007':
return ttmPin;
case '1008':
return doctorPin;
default:
return Pin;
}
};
const optionType = (obj: any, index: any) => {
const result = {
...obj,
id: obj.id,
index
};
return result;
};
const setMarkersFunction = (insListArr: TInstitution[]) => {
const tempMarkers: Array<Mkr> = [];
insListArr.forEach((marker, index: any) => {
if (marker.name.toLocaleLowerCase('tr').includes(searchStr)) {
const _marker: Mkr = {
position: {
lng: Number(marker['lng']),
lat: Number(marker['lat'])
},
icon: markerType(marker),
zIndex: marker.selected ? 999 : 100,
options: optionType(marker, index)
};
tempMarkers.push(_marker);
}
});
return tempMarkers;
};
const filterAll = async () => {
setIsInfoBoxOpen(false);
const newOnes = setMarkersFunction(ins);
setResponseMarkers(newOnes);
};
useLayoutEffect(() => {
filterAll();
}, [district, insType, markers.length, ins, searchStr]);
useEffect(() => {
const canPan = selectedMarker !== null && mapRef.current;
if (canPan) {
mapRef.current?.panTo(selectedMarker.position);
}
}, [selectedMarker]);
useEffect(() => {
if (markerId.length > 0) {
responseMarkers.forEach((mark: Mkr) => {
if (mark.options.id && mark.options.id === markerId) {
onMarkerClick(mark);
} else {
return null;
}
});
}
}, [markerId]);
useEffect(() => {
const canSetCenter = city !== null;
if (canSetCenter) {
mapRef.current?.setZoom(12);
console.log('center', center);
setCenter({
lat: Number(city.coorY),
lng: Number(city.coorX)
});
}
}, [city, district, country]);
useEffect(() => {
const canSetCenter = district !== null && district.code !== '9999';
if (canSetCenter) {
mapRef.current?.setZoom(14);
setCenter({
lat: Number(district?.coorY),
lng: Number(district?.coorX)
});
}
}, [district]);
return (
<div className="InsMap" data-testid="InsMap" id="InsMap">
<LoadScript
onError={(e) => console.log('loadscript error', e)}
googleMapsApiKey={getGmapsKeys()}
language={'tr-TR'}
>
<GoogleMap
mapContainerStyle={mapContainerStyle}
zoom={14}
options={mapOptions}
onLoad={onLoadMap}
center={convertToNumber({ lat: center.lat, lng: center.lng })}
onCenterChanged={() => mapRef.current?.getCenter().toJSON()}
>
<MapNav></MapNav>
{responseMarkers.map((marker) => {
return (
<Marker
position={marker.position}
key={marker.options.index}
icon={marker.icon}
zIndex={marker.zIndex}
onClick={() => onMarkerClick(marker)}
></Marker>
);
})}
{isInfoBoxOpen && selectedMarker && selectedMarker?.options?.type !== 'target' && (
<InfoBox
options={{
zIndex: 600,
pixelOffset: new window.google.maps.Size(-100, 0)
}}
ref={infoBoxRef}
onCloseClick={() => {
setIsInfoBoxOpen(false);
setSelectedMarker(null);
}}
position={selectedMarker.position}
zIndex={700}
>
<InsInfoCard selectedMarker={selectedMarker}></InsInfoCard>
</InfoBox>
)}
</GoogleMap>
</LoadScript>
</div>
);
};
export default InsMap;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
答: 暂无答案
评论