我正在使用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="© <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 (其数据)更改时重新渲染?
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 矩形对象。如果您单击地图上方的“更新”按钮,它将更新基础数据并将重新渲染为三角形。
<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>