reactjs react-leaflet WMSTileLayer 'params'选项会在更新任何不相关状态变量时导致Map图层闪烁

t98cgbkg  于 2022-11-04  发布在  React
关注(0)|答案(2)|浏览(117)

我正在使用react-leaflet:3.2.0来显示一个使用WMSTileLayer组件的WMS图块图层。如果我不包含params选项,它会运行得很好。如果我通过params选项包含任何内容,那么更新ANY状态变量会导致图层闪烁。
在下面的示例中,我将params={{hello:'world'}}硬编码到WMSTileLayer选项中,每次我按下一个按钮来更新一个名为dummy的完全不相关的状态变量时,Map就会闪烁。因为我可能有很多状态管理正在进行,所以它会阻止我在WMSTileLayer中使用params选项。由于我确实需要使用params选项来向WMS查询字符串添加参数,因此我被卡住了。
有人能告诉我我做错了什么吗?想必其他人也会使用这个选项。
一切帮助大大感激不尽,谢谢!
Here is a link to a gif illustrating the problem,代码如下所示。

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>
  )
}
pxy2qtax

pxy2qtax1#

我对此进行了调查,但没有找到答案。我尝试将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>
  </>)
c3frrgcw

c3frrgcw2#

正如www.example.com中所指出https://github.com/PaulLeCam/react-leaflet/issues/825#issuecomment-765349582:
这是通过引用进行道具比较的预期行为,您可以根据需要跟踪这些引用,而不是在每个渲染中创建新对象。
上面this answer示例中的实际问题是在每次重新渲染时重新创建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>
    </>
  );
}

相关问题