我使用react-传单:3.2.0来显示使用WMSTileLayer组件的WMS贴图层。如果我不包含params
选项,它就可以很好地工作。如果我通过params
选项包含任何内容,那么更新任何状态变量都会导致图层闪烁。
在下面的例子中,我将params={{hello:'world'}}
硬编码到WMSTileLayer选项中,每次我按下按钮更新一个完全不相关的状态变量dummy
时,地图就会闪烁。因为我可能有很多状态管理正在进行,它阻止我使用params
选项与WMSTileLayer。因为我真的需要使用params
选项来添加参数到WMS查询字符串,我卡住了。
谁能告诉我我做错了什么?想必其他人也使用这个选项OK。 非常感谢所有的帮助,谢谢!这是一个链接到一个gif说明问题和代码如下所示。
import React, { useState } from 'react'
import { WMSTileLayer } from 'react-leaflet'
import * as L from 'leaflet'
import 'proj4leaflet'
import proj4 from 'proj4'
import { MapContainer, TileLayer } from 'react-leaflet'
import { Button } from 'react-bulma-components';
import 'leaflet/dist/leaflet.css'
export default function Dataset(props) {
const zoomLevel = 1
const center = [51.7, -1.5]
const projName = 'EPSG:27700'
const projParams = '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs'
const crs27700 = new L.Proj.CRS(projName,
projParams,
{
resolutions: [896, 448, 224, 112, 56, 28, 14, 7, 3.5, 1.75, 0.875, 0.4375, 0.21875, 0.109375],
origin: [-238375, 1376256]
}
)
proj4.defs(projName,projParams)
const [dummy, setDummy] = useState(true)
return (
<div>
<div className="dataset-container">
<MapContainer center={center} zoom={zoomLevel} crs={crs27700} attributionControl={false} >
<WMSTileLayer
layers={'pollutant'}
url={`/mapserver/mapserv?map=/maps/pollutant.map&year=05`}
params={{hello:'world'}} // <-- comment out this line to stop the map flickering when the button is pressed
maxZoom={6}
transparent={true}
format='image/png'
opacity={0.8}
/>
</MapContainer>
</div>
<Button onClick={e => setDummy(!dummy)}>Press me</Button>{dummy ? ' dummy=true' : ' dummy=false'}
</div>
)
}
正如https://github.com/PaulLeCam/react-leaflet/issues/825#issuecomment-765349582:
所指出的那样这是预期的行为,道具比较是通过引用进行的,这是由你来跟踪这些引用,而不是在每次渲染中创建新的对象。
上面答案示例中的实际问题是每次重新渲染时都要重新创建params对象。可以使用useMemo
钩子来防止这种情况,例如:
import React, { useState, useMemo } from "react";
import { MapContainer, WMSTileLayer } from "react-leaflet";
import "leaflet/dist/leaflet.css";
export default function App() {
const [dummy, setDummy] = useState(true);
const layerParams = useMemo(() => {
return {hello: 'world'};
}, []);
return (
<>
<div>
<MapContainer
style={{ height: "400px", width: "600px" }}
center={[51.7, -1.5]}
zoom={13}
>
<WMSTileLayer
layers={"TOPO-OSM-WMS"}
url={`http://ows.mundialis.de/services/service?`}
params={layerParams}
/>
</MapContainer>
</div>
<button onClick={(e) => setDummy(!dummy)}>Press me</button>
</>
);
}
我对此进行了调查,但没有找到答案。我尝试将WMS抽象为一个单独的功能组件,但结果是相同的。我使用可公开访问的WMS和默认CRS重现了这个问题,代码较少,所以在这里发布,以防对其他人调查有用:
import React, { useState } from 'react'
import { MapContainer, WMSTileLayer } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
export default function App() {
const [dummy, setDummy] = useState(true)
return (<>
<div>
<MapContainer style={{height:"400px", width:"600px"}} center={[51.7, -1.5]} zoom={13} >
<WMSTileLayer
layers={'TOPO-OSM-WMS'}
url={`http://ows.mundialis.de/services/service?`}
params={{hello:'world'}} // <-- comment out this line to stop the map flickering when the button is pressed
/>
</MapContainer>
</div>
<button onClick={e => setDummy(!dummy)}>Press me</button>
</>)