React传单地图在数据更改时不更新数据/重新渲染

问题描述 投票:0回答:2

我正在使用react-leaflet制作每个州的县的地图,但它一次只显示一个州。理想情况下,它应该能够让用户选择感兴趣的状态,然后地图更改为仅显示该状态。我有一个 geojson,其中包含所有 50 个州的县的边界,我对其进行过滤以仅显示与当前所选州匹配的县。但是,过滤器无法重新渲染地图。问题是,数据数组确实更新了。我已经检查过它显示了正确的新过滤的 json 和正确的状态代码,但即使元素的数据字段已更改,地图也没有更改。当选择新状态时,地图的中心会发生变化(只有在我最后添加了flyToMap函数后才起作用),但我无法更新数据。保留原始州(罗德岛州)的数据

这是完整 Map 元素的代码:

import "leaflet/dist/leaflet.css";
import { MapContainer, TileLayer, GeoJSON, useMap } from "react-leaflet";
import "../../styles/Map.css";
import React, { useState, useEffect } from "react";
import WealthChart from "./WealthChart";

function WealthMap(props) {
  const [wealthCounty, setWealthCounty] = useState(props.currState);
  const [wealthData, setWealthData] = useState({});
  
  const styles = {
    height: "30vh",
    width: "30%",
    margin: "0 auto",
  };

  const stateStyles = {
    fillColor: "red",
    color: "gray",
    fillOpacity: 0.5,
    weight: 1.5,
  };

  console.log("in wealth map", props.currCounties);

  /**
   * preform api request to ACS 2021 5yr estimates S1903 table to get median household income
   * and margins of error by race/ethnicity
   */
  function getCountyWealthData(county, state) {
    console.log(`count ${county}, state ${state}`);
    // api call
  }

  /**
   * on click, get the county fips code, make api request, and set data as that data to pass to map
   */
  const onWealthCountyClick = (event) => {
    const countyName = event.target.feature.properties.NAME;
    setWealthCounty(countyName);

    const countyFIPS = event.target.feature.properties.COUNTYFP;
    getCountyWealthData(countyFIPS, props.stateFIPS);
  };

  const onEachWealthCounty = (state, layer) => {
    layer.on({
      click: onWealthCountyClick,
    });
  };


  // Function to move the map to the center of the markers after the map is loaded with new data
  function FlyMapTo(props) {
    const map = useMap();

    useEffect(() => {
      map.flyTo(props.center, props.zoom);
    });

    return null;
  }

  return (
    <div>
      <MapContainer style={styles} center={props.currCenter} zoom={8}>
        <TileLayer
          attribution="&copy; <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>"
          url="https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png"
        />
        <GeoJSON
          style={stateStyles}
          data={props.currCounties}
          onEachFeature={onEachWealthCounty}
        />
        <FlyMapTo center={props.currCenter} zoom={8} />
      </MapContainer>
      <h3>{wealthCounty}!!</h3>
      <WealthChart data={wealthData} />
    </div>
  );
}

export default WealthMap;

我知道问题是地图元素在开始时只构建一次,但是如何让它在每次 props.currCounties (其数据)更改时重新渲染?

reactjs react-hooks react-leaflet
2个回答
1
投票

React Leaflet 文档声明子组件的 props 是不可变的:

默认情况下,这些 props 应该被视为不可变的,只有 props 在此页面中明确记录为可变的将影响传单 更改时的元素。

GeoJSON API 声明 data

 属性不可变,因此这解释了为什么 
<GeoJSON>
 对象不更新(即使底层数据更新)。

您可以向

key

 对象添加 
GeoJSON
 属性,如下所示,以便在数据发生变化时触发更新:

<GeoJSON key={JSON.stringify(props.currCounties)} style={stateStyles} data={props.currCounties} onEachFeature={onEachWealthCounty} />
当数据(

props.currCounties

)更新时,
JSON.stringify(props.currCounties)
的值也会发生变化,这意味着
key
的值发生变化,从而强制重新渲染地图。

有一个

StackBlitz 演示 展示了这一操作。当地图最初加载时,它将渲染一个 GeoJSON 矩形对象。如果您单击地图上方的“更新”按钮,它将更新基础数据并将重新渲染为三角形。


0
投票
谢谢您的回答。 我遇到了类似的问题,即对中心属性进行任何更改后地图没有更新。正如 Ian 指出的那样,这是因为子组件的 props 是不可变的。添加 key 道具解决了问题。

<MapContainer key={center[0].toString()} className="w-full, h-[40vh]" center={center} zoom={4} scrollWheelZoom={false} > <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <Marker position={center}> </Marker> </MapContainer>
    
© www.soinside.com 2019 - 2024. All rights reserved.