'React way'是否真的定期重新渲染整个react-leaflet组件?

问题描述 投票:0回答:1

我正在使用react-leaflet显示带有从API加载的动态标记的地图。到目前为止,我一直在将标记加载到渲染器中,但是我意识到,每次更改任何内容(例如缩放,位置)时,渲染都不必要地重新渲染整个Leaflet Map。我想我可以删除缩放和位置状态并为此调用本地Leaflet函数,但最终我需要在初始渲染后加载我的数据,至少可以进行第二次不必要的渲染。 React是否真的设计成是首选方式?

function MyMap() {
  const [markers, setMarkers] = useState([]);

  useEffect(() => {
    console.log('useEffect');

    getMyData().then(a => {
      console.log('data load');
      setMarkers(a);
    });
  }, []);

  console.log('map render');
  return (
    <Map id='map' className='map' center={[52, 0]} zoom={6}>
      <TileLayer
        url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      />
      <LayerGroup>
        {markers.map(a => {
          return (
            <Marker
              key={a._id}
              position={[a.location.latitude, a.location.longitude]}
              icon={myIcon}
            />
          );
        })}
      </LayerGroup>
    </Map>
  );
}

控制台输出:

map render
useEffect
data load
map render

我很想通过以普通的Leaflet方式动态添加标记来解决此问题:

L.marker([50.5, 30.5]).addTo(map);

但是,这在react-leaflet中显得不平凡。在寻找如何动态添加标记的过程中,我遇到了React Leaflet:动态添加标记,特别是top answer建议不要这样做。关联的jsfiddle会为每次点击重新呈现整个地图。也许还好吗?

react-leaflet
1个回答
0
投票

为了防止在添加标记后重新渲染地图,可以应用以下更改列表:

a]中处于MyMap状态的markers(父级)组件中,保持跟踪only从数据源加载的标记

注意:一旦在此组件中单击地图,markers状态将不会更新

function MyMap() {
  const [markers, setMarkers] = useState([]);

  useEffect(() => {
    console.log("useEffect");
    getMyData().then((data) => {
      console.log("data load");
      setMarkers(data);
    });
  }, []);

  console.log("map render");
  return (
    <Map id="map" className="map" center={[52, 0]} zoom={4}>
      <TileLayer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      />
      <MyLayer defaultMarkers={markers} />
    </Map>
  );
}

b)引入状态为markers的单独的(子)组件来跟踪从数据源加载的标记(使用通过props传递的默认值进行设置),以及在地图click事件上添加的标记:

function MyLayer(props, ref) {
  const { defaultMarkers } = props;
  const [markers, setMarkers] = useState(defaultMarkers);
  const mapProps = useLeaflet();


  const addMarker = useCallback((e) => {
    const newMarker = {
      location: e.latlng,
    };
    console.log(newMarker);
    setMarkers((existingMarkers) => [...existingMarkers, newMarker]);
  }, []);


  useEffect(() => {
    setMarkers(defaultMarkers);  
    mapProps.map.on('click',addMarker)
  }, [addMarker,mapProps,defaultMarkers]);


  return (
    <LayerGroup>
      {markers.map((marker, idx) => {
        return (
          <Marker
            key={idx}
            position={[marker.location.lat, marker.location.lng]}
          />
        );
      })}
    </LayerGroup>
  );
}

这里是demo

© www.soinside.com 2019 - 2024. All rights reserved.