0

当用户单击某个 Geojson 功能时,我正在尝试添加标记。我是 react 和 react-leaflet 的新手,我正在尝试使用 useState 挂钩来完成这项任务。我在这个问题上被困了几天。

这是我的App.js。我导入数据,为我的标记创建一个状态变量和设置器,并将这些项目传递给我的组件<MyData/><MyMarkers/>.

import "./styles.css";
import React, { useState } from 'react'
import {MapContainer, TileLayer} from 'react-leaflet'
import L from 'leaflet'
import someData from './data.geojson'

import MyData from './components/MyData.js'
import MyMarkers from './components/MyMarkers.js'


// import bugged marker
import icon from 'leaflet/dist/images/marker-icon.png';
import iconShadow from 'leaflet/dist/images/marker-shadow.png';

// set the default icon
let DefaultIcon = L.icon({
    iconUrl: icon,
    shadowUrl: iconShadow,
    iconSize: [25, 41],
    iconAnchor: [12, 41],
    popupAnchor: [2, -40],
});
L.Marker.prototype.options.icon = DefaultIcon;




export default function App() {
  // create state variable and setter for the markers
  let [markers, setMarkers] = useState([])
  // import geojson data
  let data= JSON.parse(someData)

  return (
    <>
   <MapContainer
      doubleClickZoom={false}
      id="mapId"
      zoom={14}
      center={[37.37569444, -91.5528056]}
    >
      <TileLayer
        url="https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}"
        attribution="Tiles &copy; Esri &mdash; Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri"
      />

    <MyData data={data} markers = {markers} setMarkers ={setMarkers}/> 
    {markers.length >0 && <MyMarkers markers={markers}/>}

    </MapContainer>
   </>
  );
}

这是我的MyData组件,它显示 geojson 数据。它接收 geojson 数据、对象数组和设置标记状态的函数。

import React from 'react';
import { GeoJSON } from 'react-leaflet';



function MyData ({data, markers, setMarkers})  {
    // data not null, return the geojson component      
    if (data) {  
      return <GeoJSON pathOptions={ { color: "red" } } data={data} eventHandlers={{
        // click handler for geojson component
        click:  (e) => {
          // push the latlng object to the markers array
          markers.push(e.latlng)
          // set the state using the setter...why does this not render markers?
          setMarkers(markers)
             
        }
        }}  />;
    } else {
      return null;
    }
  };


export default MyData

这是我的MyMarkers组件,它遍历标记数组,我将其作为道具传递,理想情况下在每个位置创建标记组件。(这不起作用)

import React from 'react';
import {  Marker } from 'react-leaflet';


function MyMarkers ({markers}) {
   // check length of the markers
  if (markers.length > 0){
    // iterate through the array of markers creating a marker with unique id at given latlngs
    markers.map((position, id) => { 
      return <Marker key={id} position={position}/>
    })    

} else {
  return null;
}
};


export default MyMarkers

我可以在地图上绘制我的 geojson 数据,但无法在单击我的<MyData/>组件时显示标记。我在这里想念什么?我的理解是,当尝试更新同级组件(<MyData/>​​和<MyMarkers/>)的状态时,需要将状态提升到一个共同的祖先(<App/>在这种情况下),这是我试图做的。如何从内部成功更新状态 onclick<MyData/>以呈现标记?

是上面问题和代码的沙箱。

谢谢

4

1 回答 1

1

-首先你正在改变数组。因此,组件不会重新渲染。您应该克隆标记,然后推送新状态。

<GeoJSON
        pathOptions={{ color: "red" }}
        data={data}
        eventHandlers={{
          // click handler for geojson component
          click: (e) => {
            const newMarkers=[...markers];
            newMarkers.push(e.latlng);
            console.log(newMarkers)
            setMarkers(newMarkers);
          }
        }}
      />

- 其次,您已经在此处检查了要渲染的标记markers.length !== 0,我认为它应该高于 0:{markers.length > 0 && <MyMarkers markers={markers} />}

为什么要重新检查内部Markers组件。把事情简单化:

function MyMarkers({ markers }) {      
    // iterate through the array of markers creating a marker with unique id at given latlngs
    return markers.map((position, id) => {
      return <Marker key={id} position={[position.lat, position.lng]} />;
    });
 
}

最后但同样重要的是,标记 url 图标不正确。将其替换为

  iconUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png',

例如

演示

于 2021-08-28T11:26:50.217 回答