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

提问人:barisdevjs 提问时间:11/17/2023 更新时间:11/17/2023 访问量:12

问:

我有一个这样的父组件,其中包括 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 的实例enter image description here

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>

javascript reactjs 谷歌地图 标记

评论

1赞 Yrll 11/24/2023
你能尝试创建一个最小的可重复的例子吗?就像一个代码沙盒,这样社区就可以更好地帮助你。
1赞 barisdevjs 11/24/2023
这很难做到,但我会尝试。许多服务调用都依赖于它

答: 暂无答案