React Leaflet地图数据更新后不重新渲染问题求助
问题
我用react-leaflet开发美国各州郡县地图,需求是用户选择州后,地图只显示对应州的郡县。我已经通过GeoJSON过滤出当前选中州的郡县数据,也确认了数据数组已经更新为正确的过滤后内容,但<GeoJSON>组件的data属性变更后地图并未重新渲染——只有地图中心能随选择切换(通过FlyMapTo函数实现),始终显示初始州(罗德岛)的内容。
完整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数据变化时重新渲染?
解决方案
1. 给GeoJSON组件添加唯一key
react-leaflet的<GeoJSON>组件默认依赖数据引用的变化触发重渲染,如果只是修改数组内容而引用不变,组件不会更新。给组件绑定一个随选中州变化的唯一key(比如州的FIPS编码props.stateFIPS),当key改变时,组件会强制重新挂载,从而加载新的GeoJSON数据:
<GeoJSON key={props.stateFIPS} // 添加唯一key,随选中州变化 style={stateStyles} data={props.currCounties} onEachFeature={onEachWealthCounty} />
2. 确保过滤后的GeoJSON数据是新引用
如果过滤数据时直接操作原数组,或者过滤后返回的是原数组的子集引用(未通过slice()、展开运算符[...]生成新数组),React的浅比较会认为data属性没有变化。过滤操作要返回新数组,示例:
// 过滤时生成新数组 const filteredCounties = [...originalCounties.filter(county => county.properties.STATEFP === targetStateFIPS)];
3. 修正FlyMapTo的useEffect依赖
原代码中FlyMapTo组件的useEffect没有设置依赖项,会导致每次组件渲染都触发flyTo操作。添加正确的依赖项,只在地图中心或缩放级别变化时执行:
function FlyMapTo(props) { const map = useMap(); useEffect(() => { map.flyTo(props.center, props.zoom); }, [props.center, props.zoom, map]); // 添加依赖项 return null; }
内容的提问来源于stack exchange,提问作者kw5
相关产品推荐
相关产品推荐

