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

React-leaflet: how to update marker positions?

我不明白如何使用 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 将移除标记并放置新标记,而不是更新原始标记的位置。

所以我的问题是。我做得对还是这不是最高效的方式?

谢谢!

Am I doing it right?

是的,你是。你应该这样使用它。

this is not the most performant way

你也在。 这不是最高效的方法。因为一旦 props 改变,就会强制重新渲染 react 组件。这将包括删除存在的标记和添加所有新标记。这是因为 React 不知道什么是以前的 props 以及什么是新的东西。

您可以使用 keys while mapping your data. Read more about it here

来解决这个问题

另一种方法是分别计算您的 addedMarkersremovedMarkersupdatedMarkers,然后使用它们重新呈现您的视图。但是,如果您的应用程序要使用的标记数量相当少,那可能会成为一个大麻烦。

如果您使用的是 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 行调用挂钩更新状态,更新的 defaultPosition 进入 Marker 组件并重新渲染它。

之前的代码:

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>
  );
}

没有钩子是不可能的。