React useCallback 函数在无限循环中运行

React useCallback function runs in infinite loop

我正在尝试使用 leaflet-geoman library in a React project. I need to create a custom toolbar button that enables and disables global drag mode

单击工具栏按钮时,map.pm.enableGlobalDragMode(); 函数启用全局模式。再次单击工具栏按钮时,map.pm.disableGlobalDragMode(); 导致 useCallback 函数 afterClick 运行 无限循环。

codesandbox.io

useDraw.js

import React from "react";

const useDraw = (mapRef) => {
  const afterClick = React.useCallback(() => {
    console.log("afterclick");
    const map = mapRef.current.leafletElement;
    let editDragEnabled = false;
    if (!editDragEnabled) {
      console.log("enable");
      map.pm.enableGlobalDragMode();
      editDragEnabled = true;
    } else {
      console.log("disable");
      map.pm.disableGlobalDragMode();
      editDragEnabled = false;
    }
  }, [mapRef]);

  React.useEffect(() => {
    const map = mapRef.current.leafletElement;

    var actions = ["finishMode"];
    map.pm.addControls({
      drawRectangle: false,
      drawMarker: false,
      drawPolyline: false,
      drawPolygon: false,
      drawCircle: false,
      drawCircleMarker: false,
      removalMode: false,
      editMode: false,
      cutPolygon: false,
      dragMode: false
    });
    map.pm.Toolbar.createCustomControl({
      name: "DragEdit",
      block: "custom",
      title: "Edit and Drag Layers",
      onClick: () => afterClick(),
      actions: actions,
      toggle: true
    });
  }, [mapRef, afterClick]);
};

export default useDraw;

问题是,当enableGlobalDragMode(或禁用)原始拖动按钮的控件被激活时,这将禁用您的自定义按钮(因为所有其他按钮都被禁用,因此只能使用一种模式活跃)。

我建议使用 enableGlobalDragMode 函数中的代码而不是调用它,这会导致控件发生变化:

const afterClick = React.useCallback(() => {
    console.log("afterclick");
    const map = mapRef.current.leafletElement;

    const layers = L.PM.Utils.findLayers(map);
    let dragMode = map.pm._customModeEnabled || false;
    if(!dragMode){
      console.log("enable");
      layers.forEach((layer)=>{
        layer.pm.enableLayerDrag();
      })
    }else{
      console.log("disable");
      layers.forEach((layer)=>{
        layer.pm.disableLayerDrag();
      })
    }
    map.pm._customModeEnabled = !dragMode;
  }, [mapRef]);