react中Modal组件与openlayers地图实例化在feature要素绘制与清除等场景中存在的bug

news/2024/7/15 17:03:11 标签: react.js, bug

在有地图的实际业务中会有一个经常的场景,那就是地图的初始化,一般如下:

 useEffect(() => {
    initMap();
  }, [visible]);

我们经常利用Modal组件中open属性状态true与false来作为监听地图初始化的条件。

      <Modal
        title={<div className="title">新增设备</div>}
        width={1120}
        className="argicul-modal"
        footer={null}
        centered
        closable={true}
        onCancel={onCancel}
        open={visible}>
        ......
     </Modal>

对于一般的业务处理来说,通过监听一个状态决定地图的实例化是没问题的。

bug_23">bug问题:

如果需要在Modal组件上这个地图上点线面要素的添加删除、点线面要素的绘制交互与清除等操作时,会出现一个bug:就是每次关闭Modal组件后再打开,会发现再进行添加或删除要素失效,清除再一次绘制完的要素也会失效。
1.如:第一次打开Modal时,添加与删除这个点要素,正常实现。当关闭组件再次打开操作时,发现删除无效,添加点要素后位置也没更新。在这里插入图片描述

bug_26">bug原因:

一般我们可能首先回去寻找要素绘制与删除的逻辑是否存在问题,花费大量时间发现没错。
出现这个bug最主要的原因就是每一次监听map实例化的条件变一次,map就会再实例化一次,简而言之就是每次关闭再打开的这个操作会导致map多次实例化,Modal组件上会渲染多层map地图,我们第一次对要素的各种操作其实是在第一个实例化的map上,也就是视图上最底下那层。因此,我们对于要素的各种操作实际上生效了,只是被后面实例化的map图层掩盖了,因而表现出失效的假象。

bug_29">bug解决方法:

既然我们弄清楚了是map实例化多次导致的,那么接下来就是想办法让**map在一开始只实例化一次。**所以需要一个在此页面展示时只变化一次的一个状态值。一般点击到Modal组件的父组件这各页面时,找到此时让map实例化一次的条件。
一般两种情况:
1.Modal组件的父组件的props传值参数中是否有唯一变化的 “标识” ,比如有多个tabs组件,Modal就在其中一个tabs组件中,看看每个tabs组件从其父组件上传过来的props中是否有区别tabs的 “标识”。(如果实在没有再看看父组件中有办法传一个“标识”给子组件的props不)
比如说此时我有如下tabs组件,其中每个tab的props中有个属性不同:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
那么监听的条件找到了,拿到这个值,监听这个值,在这里还会有一个bug,如果直接监听这个值,会出现以下bug
Too many re-renders. React limits the number of renders to prevent an infinite loop.
原因在这篇博客中:https://blog.csdn.net/fish_skyyyy/article/details/119137987
解决办法:在Modal打开的点击事件中进行值的判断与状态的设置,然后在地图上监听。

 const [mapvisible, setmapvisible] = useState(false);
 //打开Modal页面的按钮事件
 const addDevice = () => {
    setVisible(true);
    if(props.title.props.children=='农情设备'){
      setmapvisible(true)
     }
  };
   useEffect(() => {
    initMap();
  }, [mapvisible]);

2.一般在“链式组件”的使用场景中(点击组件A弹出B,点击B弹出C)
比如在B组件中:

const SelectDialog = forwardRef((props, ref) => {
    const [selectedItem, setSelectedItem] = useState("rtk");
    const [visible, setVisible] = useState(false);
    const [mapvisible, setmapvisible] = useState(false);
    const rtkLandRef = useRef<any>(null);
    //使用useImperativeHandle进行上下传递方法
    useImperativeHandle(ref, () => ({
        setVisible,
        setmapvisible
    }));
    const selectItem = () => {
        setVisible(false);
        if (selectedItem == "rtk") {
            //组件C(RTKLand)可以使用这两个方法,且B组件的状态值也可带入
            rtkLandRef.current?.setVisible(true);
            rtkLandRef.current?.setmapvisible(true);
        } 
    }
    const select = (type: string) => {
        setSelectedItem(type);
    }

return (
        <div>
            <Modal open={visible} width={680} closable={false} onCancel={onCancel} centered forceRender={true} footer={false} bodyStyle={{ textAlign: "center", padding: 48 }}>
                <div className={`Land-item  ${selectedItem == 'rtk' ? 'Land-item-selected' : ''}`} onClick={() => { select('rtk') }}>打点仪数据录入</div>      
            </Modal>
            <RTKLand ref={rtkLandRef}></RTKLand>
        </div>
    )
}

这样C组件(RTKLand)就可以拿到mapvisible的状态值进行map实例化监听,点击B组件时才会改变一次mapvisible的状态值,在C组件中再无论打开还是关闭C组件中的Modal组件就不会多次渲染map了。

const RTKLand = forwardRef((props, ref) => {
  const [visible, setVisible] = useState(false);
  const [mapvisible, setmapvisible] = useState(false);
  useImperativeHandle(ref, () => ({
    setVisible,
    setmapvisible
  }));
    useEffect(() => {
    initMap();
  }, [mapvisible]);
return (
    <Modal
      title={<div className="rtk-title">{title}</div>}
      open={visible}
      width={1120}
      onCancel={onCancel}
      footer={null}
      centered>
      ......
  </Modal>
}

http://www.niftyadmin.cn/n/52360.html

相关文章

2021年新公开工业控制系统严重漏洞汇总

声明 本文是学习ITOT一体化工业信息安全态势报告&#xff08;2019&#xff09;. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 工业互联网安全威胁 2021年新公开工业控制系统严重漏洞 缓冲区溢出漏洞 缓冲区溢出&#xff08;buffer overflow&…

python之try except的使用

1,try-except常用语法&#xff1a; try仅有一块&#xff0c;但是except可以有多个 try:可能产生异常的代码块 except [ (Error1, Error2, ... ) [as e] ]:处理异常的代码块1 except [ (Error3, Error4, ... ) [as e] ]:处理异常的代码块2 except [Exception]:处理其它异常 …

Java反射

首先回忆一下之前如何使用一个Java类&#xff1f; 从我们java正常使用说起&#xff0c;先定义一个类 Car 后创建对象,使用对象 new Car(); 这是正常的使用,已知某个类,创建该类的对象. 正向使用。 这种写法,把代码直接写死了,不能变了,固定了 但是框架需要为我们处理…

idea编写vue项目没有提示的坑

搜到到的方法90%是修改idea设置中的filetype设置中的HTML识别&#xff0c;也就是这种方式 但是这种方式会有一些问题&#xff0c;虽然idea能成功识别vue文件了&#xff0c;但是在编写JavaScript并且往HTML代码中放的时候就出问题了 所以说不能修改HTML识别&#xff0c;应该是…

vscode执行Python输出exited with code=9009 in 0.655 seconds

vscode执行Python输出exited with code9009 in 0.655 seconds 想用vscode写个脚本&#xff0c;用自己电脑配置了下vscode的python环境&#xff0c;结果点击右上角三角图标运行时却只会输出exited with code9009 in 0.655 seconds 这就不太理解了&#xff0c;我在公司时是能正…

git中patch的用法

Git 的 patch 用法是指通过创建一个补丁文件来修改或提交 Git 仓库中的代码。 一个 patch 文件是一种文本文件&#xff0c;它记录了将要在仓库中执行的代码更改。您可以创建补丁文件并将其发送给其他人&#xff0c;或者通过从 patch 文件中应用代码更改来更新仓库。 使用 Git…

LeetCode·每日一题·1223.掷骰子模拟·记忆化搜索

作者&#xff1a;小迅链接&#xff1a;https://leetcode.cn/problems/dice-roll-simulation/solutions/2103471/ji-yi-hua-sou-suo-zhu-shi-chao-ji-xiang-xlfcs/来源&#xff1a;力扣&#xff08;LeetCode&#xff09;著作权归作者所有。商业转载请联系作者获得授权&#xff0…

程序的翻译环境和执行环境

程序环境和预处理&#x1f996;程序的翻译环境和执行环境&#x1f996;详解编译链接&#x1f433; 翻译环境&#x1f433; 详解编译过程&#x1f433; 运行环境&#x1f996;预处理详解&#x1f433; 预定义符号&#x1f433; #define&#x1f980; #define 定义标识符&#x1…