React-leaflet:如何更新标记的位置?

4

我不明白如何使用react-leaflet正确更新我的标记。参考以下示例:

import React from 'react';
import { render } from 'react-dom';
import { connect } from 'react-redux';
import { Map, Marker, TileLayer } from 'react-leaflet';

const map = props => (
  <Map center={[51.505, -0.09]} zoom={13}>
    <TileLayer
      url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
    />
    {props.markers.map(m => (
      <Marker position={m.position} />
    ))}
  </Map>
);

const mapStateToProps = state => ({
  markers: state.markers // array of objects with positions. this can change
});

render(connect(mapStateToProps)(map), document.getElementById('map-container'));

这个方法能够工作,但我不确定是否是正确的方法。因为在这种情况下,当标记更新它们的位置(或者有更多的标记)时,Leaflet会删除标记并放置新的标记,而不是更新原始标记的位置。

所以我的问题是,我这样做对吗?或者还有更高效的方式吗?

谢谢!


我会说,这取决于你的使用情况。例如,你有3个标记,每次更新它们的位置。因此,你可以在特定的标记上应用setLatLng()(这是纯leaflet函数,在react-leaflet中应该有类似的函数)。在另一种情况下,你收到新的标记,而不是旧的3个标记。可能是2、4、5个。所以它们与旧的没有任何关系。在这种情况下,你应该删除所有标记,并像你的方法一样添加新的标记。当然,这样做的性能不佳,但这是唯一的方法。 - tomen
2个回答

5

我这样做对吗?

是的,没错。你应该这样使用。

这不是最有效率的方法

你说得对。这不是最有效率的方法,因为一旦props改变,它就会强制重新渲染react组件。这将包括删除已存在的标记并添加所有新标记。这是因为React不知道哪些是来自先前的props,哪些是新内容。

您可以通过在映射数据时使用keys来解决此问题。更多信息请阅读 这里

另一种方法是单独计算您的addedMarkersremovedMarkersupdatedMarkers,并使用它们重新渲染您的视图。然而,如果您的应用程序要使用较少数量的标记,那么这可能会变成一个大麻烦。


0
如果你使用的是 React 16+,那么你可以使用 React Hooks。
function Map() {
  let [map, setMap] = useState(null);

  const [, updateState] = React.useState();
  const forceUpdate = React.useCallback(() => updateState({}), []);
  console.log('defaultPosition', defaultPosition);
  return (
    <div>
      <div className="map__container" onMouseUp={forceUpdate}>
        <MapContainer center={defaultPosition} zoom={13} whenCreated={setMap}>
          <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
          <Marker position={defaultPosition}></Marker>;
        </MapContainer>
      </div>
      {map ? <DisplayPosition map={map} /> : null}
    </div>
  );
}

3和4行调用钩子更新状态,并在Marker组件中更新defaultPosition并重新渲染它。

之前的代码:

import {
  MapContainer,
  TileLayer,
  Marker,
  MapConsumer,
  useMapEvent,
} from 'react-leaflet';

let defaultPosition = [48.864719, 2.349]; // Paris position
let [position, setPosition] = ['', ''];

function DisplayPosition({ map }) {
  [position, setPosition] = useState(map.getCenter());
  map
    ? (defaultPosition = [
        Number(map.getCenter().lat.toFixed(4)),
        Number(map.getCenter().lng.toFixed(4)),
      ])
    : [48.864719, 2.349];
  const onClick = useCallback(() => {
    map.setView([48.864716, 2.349], 13);
  }, [map]);
  // console.log('markerPos', markerPos);
  const onMove = useCallback(() => {
    setPosition(map.getCenter());
  }, [map]);

  useEffect(() => {
    map.on('move', onMove);
    return () => {
      map.off('move', onMove);
    };
  }, [map, onMove]);

  return (
    <p>
      latitude: {position.lat.toFixed(4)}, longitude: {position.lng.toFixed(4)}{' '}
      <button onClick={onClick}>reset</button>
    </p>
  );
}

没有钩子是不可能的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接