react中Modal组件与openlayers地图实例化在feature要素绘制与清除等场景中存在的bug
创始人
2024-05-24 17:40:51
0

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

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

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

      
新增设备
}width={1120}className="argicul-modal"footer={null}centeredclosable={true}onCancel={onCancel}open={visible}>......

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

bug问题:

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

bug原因:

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

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(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 (
visible} width={680} closable={false} onCancel={onCancel} centered forceRender={true} footer={false} bodyStyle={{ textAlign: "center", padding: 48 }}>
`Land-item ${selectedItem == 'rtk' ? 'Land-item-selected' : ''}`} onClick={() => { select('rtk') }}>打点仪数据录入
rtkLandRef}>
) }

这样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 (
{title}
}open={visible}width={1120}onCancel={onCancel}footer={null}centered>...... }

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...