首页 > 解决方案 > 如何使用 react + redux 在传单 v3 中获取地图属性和处理事件?

问题描述

我是 react redux(和钩子)的新手,我一直在关注这个通用教程:

我也对使用 react-leaflet 感兴趣,在撰写本文时,它在使用钩子的 v3 上。我已经能够加载包含 latlng 数组的数据来生成标记:

import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { Map, MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
import { Icon } from "leaflet";
import "../../css/app.css";
import { useSelector, useDispatch } from "react-redux";
import { getMarkers, selectMarkers } from "../features/markerSlice";

export const LeafMap = () => {
    //marker state
    const stateMarker = useSelector(state => state.marker);
    const dispatch = useDispatch();
    useEffect(() => {dispatch(getMarkers());}, [dispatch]);

    // map state
    const stateMap = useSelector(state => state.map)

    if (stateMarker.markers.length > 0) {
        return (
            <MapContainer center={stateMap.center} zoom={stateMap.zoom} scrollWheelZoom={true}>
              <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              />
              {stateMarker.markers.map(el => (
                <Marker position={[el.latitude, el.longitude]}/>
              ))}
            </MapContainer>
        );
    } else {
        return (
            <MapContainer center={stateMap.center} zoom={stateMap.zoom} scrollWheelZoom={true}>
              <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              />
            </MapContainer>
        );
    }

}

目前,我对如何处理点击事件(标记点击)以及如何访问地图状态(当前边界框、当前缩放级别等)感到非常困惑。我遇到错误,例如我无法访问地图状态,除非它位于子组件中,或者无法识别 onclick 处理程序等。

我希望最终能够根据缩放和边界框动态加载标记,然后单击标记以放大它。这可能是因为我是 react redux 和 hooks 的绝对起点。

我不是在寻找任何人来为我编写代码,但是如果有人可以就如何完成这些提供一般指导,那将非常感激!

标签: reactjsreact-reduxleafletreact-hooksreact-leaflet

解决方案


要处理标记点击事件,请使用eventHandlersprop 并在Markerscomp 上监听 click 事件,如下所示:

const CustomMarkers = () => {
    const map = useMap();
    return markers.map((el, i) => (
      <Marker
        key={i}
        position={[el.latitude, el.longitude]}
        icon={icon}
        eventHandlers={{
          click: () => {
            console.log("marker clicked", el);
            console.log(map.getZoom());
          }
        }}
      />
    ));
  };

useMap您可以像这样导出每个标记元素,并在单击每个标记时使用钩子获取有关地图的信息。

根据缩放级别动态加载标记。一个例子可能是这样的:你有一个 btn。当您单击它时,您会动态添加一个标记,该标记具有一个事件侦听器以进一步缩放地图。例如,仅当当前地图缩放级别为 6 时才会触发此操作。

 function AddMarkerOnClick({ map }) {
        const onClick = () => {
          console.log(map.getZoom());
          if (map?.getZoom() === 6) {
            L.marker([39.77, -106.23], { icon })
              .addTo(map)
              .addEventListener("click", () => map.setZoom(4));
          }
        };
    
        return <button onClick={onClick}>Add marker on click</button>;
      }

...
return (
<>
      <AddMarkerOnClick map={map} />
      <MapContainer
        center={position}
      ...
</>
)

为了能够获得地图参考,您需要将您的自定义组件MapContainer作为子组件或获取MapContainer的map instanceusing属性,然后将其传递给您的自定义组件。whenCreated

示例演示


推荐阅读