繁体   English   中英

React 中的 Strict Mode 提示 Open Layer 复制错误

[英]Strict Mode in React prompts Open Layer duplication errors

版本: "ol": "^6.14.1",

我正在尝试在 React 中向 OpenLayer map 添加标记,但是每当我单击 map 时,我都会收到错误消息: Uncaught AssertionError: Assertion failed. See https://openlayers.org/en/v6.14.1/doc/errors/#58 for details. Uncaught AssertionError: Assertion failed. See https://openlayers.org/en/v6.14.1/doc/errors/#58 for details. 来自代码map.addLayer(newMarkersLayer); .

错误指出: Duplicate item added to a unique collection. For example, it may be that you tried to add the same layer to a map twice. Check for calls to map.addLayer() or other places where the map's layer collection is modified. Duplicate item added to a unique collection. For example, it may be that you tried to add the same layer to a map twice. Check for calls to map.addLayer() or other places where the map's layer collection is modified.

发生这种重复是因为React.StricMode包裹在我的应用程序周围。 如果我禁用严格模式,单击 map 会添加一个标记。

我不想禁用严格模式,因为我仍然认为错误来自我在 React 中使用写得不好的useEffect()实现 map 的方式。

我应该如何在 React 中的 OpenLayers map 上添加标记,以便 StrictMode 不会添加重复项?

Map 组件:

import { useState, useEffect, useRef } from 'react';
// import ModalUI from '../UI/ModalUI';
import classes from './MapUI.module.css';
import { drawerActions } from '../Rooms/Drawers/drawerSlice';

import 'ol/ol.css';
import { Map, View, Overlay, Feature } from 'ol';
import Point from 'ol/geom/Point';
import { Vector as VectorLayer } from 'ol/layer';
import VectorSource from 'ol/source/Vector';
import { fromLonLat, toLonLat } from 'ol/proj';
import { toStringHDMS } from 'ol/coordinate';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';

import PopUp from './PopUp';
import { useDispatch } from 'react-redux';

export default function MapUI() {
  const dispatch = useDispatch();
  const mapRef = useRef();
  const popup = useRef();
  const [coordinates, setCoordinates] = useState('');
  const [newMarker, setNewMarker] = useState(
    new Feature({
      geometry: new Point([[]]),
      name: '',
    })
  );

  const [newMarkersLayer] = useState(
    new VectorLayer({
      properties: { name: 'newMarkers' },
      source: new VectorSource({
        features: [newMarker],
      }),
    })
  );

  const closePopup = () => {
    map.getOverlayById('map-popup').setPosition(undefined);
    map.removeLayer(newMarkersLayer);
  };

  const [map] = useState(
    new Map({
      target: '',
      layers: [
        new TileLayer({
          source: new OSM(),
        }),
        new VectorLayer({
          properties: { name: 'existingMarkers' },
          source: new VectorSource({
            // features: [marker],
          }),
        }),
      ],
      view: new View({
        center: fromLonLat([26.08, 44.46]),
        zoom: 15,
        minZoom: 10,
        maxZoom: 20,
      }),
    })
  );

  useEffect(() => {
    const overlay = new Overlay({
      element: popup.current,
      id: 'map-popup',
      autoPan: {
        animation: {
          duration: 250,
        },
      },
    });
    // console.log('useEffect in MapUI.jsx');

    map.addOverlay(overlay);
    map.setTarget(mapRef.current);
    map.on('singleclick', function (evt) {
      map.addLayer(newMarkersLayer);
      dispatch(drawerActions.closeDrawer());
      newMarker.getGeometry().setCoordinates(evt.coordinate);
      // console.log(typeof evt.coordinate);

      setCoordinates(toStringHDMS(toLonLat(evt.coordinate)));
      overlay.setPosition(evt.coordinate);
    });
  }, [newMarkersLayer, map, newMarker, dispatch]);

  return (
    <>
      <div
        style={{ height: '100%', width: '100%' }}
        ref={mapRef}
        className='map-container'
      />
      <div id='map-popup' className={classes['ol-popup']} ref={popup}>
        <PopUp coordinates={coordinates} closePopup={closePopup} />
      </div>
    </>
  );
}

React 严格模式故意双重调用某些处理程序以强制您制作干净且可重用的组件 - 您的组件不是。

要么接受这个事实并删除严格模式,这只会成为你的障碍,或者 - 如果你打算制作可重用的组件 - 尝试遵循它的指导方针。 正如Mike指出的那样,您可能不应该在每次单击时创建一个新层。

另外,我想指出在https://github.com/mmomtchev/rlayers上有 OpenLayers 的 React 组件(我是作者)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM