尝试使用 react-leaflet 在点击时应用缩放

Trying to apply zoom on click with react-leaflet

我正在尝试将传单地图 https://leafletjs.com/examples/choropleth/ 的一些功能复制到 react/typeScript,但是当我尝试添加功能以放大它损坏的功能时出现错误,这是我正在处理的代码

import Leaflet from 'leaflet';
import React, {
  useRef, RefObject,
} from 'react';
import {
  MapContainer, TileLayer, GeoJSON, useMap,
} from 'react-leaflet';
import styled from 'styled-components';

import { statesData } from './statesData';
import './style.css';

const EmployerLocationMap = () => {
  const geoJson: RefObject<Leaflet.GeoJSON> = useRef(null);
  const map = useMap();

  const highlightFeature = (e: Leaflet.LeafletMouseEvent) => {
    const layer = e.target;

    layer.setStyle({
      color: '#666',
      dashArray: '',
      fillOpacity: 0.7,
      weight: 5,
    });
  };

  const resetHighlight = (e: Leaflet.LeafletMouseEvent) => {
    geoJson.current?.resetStyle(e.target);
  };

  const zoomToFeature = (e: Leaflet.LeafletMouseEvent) => {
    map.fitBounds(e.target.getBounds());
  };

  return (
    <CardContainer>
      <Row>
        <Col width='60%'>
          <MapContainer
            center={[37.8, -96]}
            zoom={3}
          >
            <TileLayer
              attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
              url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
            />
            <GeoJSON
              data={statesData}
              key='usa-states'
              ref={geoJson}
              style={() => {
                return {
                  color: 'white',
                  dashArray: '3',
                  fillColor: '#f0f0f0',
                  fillOpacity: 0.7,
                  opacity: 1,
                  weight: 2,
                };
              }}
              onEachFeature={(__, layer) => {
                layer.on({
                  click: (e) => {
                    zoomToFeature(e);
                  },
                  mouseout: (e) => {
                    resetHighlight(e);
                  },
                  mouseover: (e) => {
                    highlightFeature(e);
                  },
                });
              }}
            />
          </MapContainer>
        </Col>
      </Row>

    </CardContainer>
  );
};

export default EmployerLocationMap;

当我启动前端时,我在控制台上收到此错误:

Uncaught Error: No context provided: useLeafletContext() can only be used in a descendant of <MapContainer>

at useLeafletContext

我不明白哪里出了问题,我已经看到了几个关于它的实现,它们看起来都一样。

useMap 只能在本身是 <MapContainer> 的 child/descendant 的组件中使用。 https://react-leaflet.js.org/docs/api-map/#usemap

Hook providing the Leaflet Map instance in any descendant of a MapContainer.

在这里你尝试在你的 EmployerLocationMap 组件中调用 useMap,其中 包含 一个 <MapContainer>,但显然不是 一个人的后代

针对您的情况的解决方案可能是将地图逻辑分离到另一个组件中,您可以将其放置在 <MapContainer>:

const EmployerLocationMap = () => {
  return (
    <CardContainer>
      <Row>
        <Col width='60%'>
          <MapContainer
            center={[37.8, -96]}
            zoom={3}
          >
            <TileLayer
              attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
              url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
            />
            <MapContent />
          </MapContainer>
        </Col>
      </Row>

    </CardContainer>
  );
};

const MapContent = () => {
  const geoJson: RefObject<Leaflet.GeoJSON> = useRef(null);
  const map = useMap();

  const highlightFeature = (e: Leaflet.LeafletMouseEvent) => {
    const layer = e.target;

    layer.setStyle({
      color: '#666',
      dashArray: '',
      fillOpacity: 0.7,
      weight: 5,
    });
  };

  const resetHighlight = (e: Leaflet.LeafletMouseEvent) => {
    geoJson.current?.resetStyle(e.target);
  };

  const zoomToFeature = (e: Leaflet.LeafletMouseEvent) => {
    map.fitBounds(e.target.getBounds());
  };

  return (
            <GeoJSON
              data={statesData}
              key='usa-states'
              ref={geoJson}
              style={() => {
                return {
                  color: 'white',
                  dashArray: '3',
                  fillColor: '#f0f0f0',
                  fillOpacity: 0.7,
                  opacity: 1,
                  weight: 2,
                };
              }}
              onEachFeature={(__, layer) => {
                layer.on({
                  click: (e) => {
                    zoomToFeature(e);
                  },
                  mouseout: (e) => {
                    resetHighlight(e);
                  },
                  mouseover: (e) => {
                    highlightFeature(e);
                  },
                });
              }}
            />
  );
};