arrays - useState setter 方法不更新数组
问题描述
我正在使用反应钩子在反应中编写一个谷歌地图组件,并且我正在将状态中的谷歌地图标记和多边形数组存储为一个称为覆盖的数组。当我从地图中清除覆盖时,我用一个空数组调用 setOverlays,但状态永远不会改变。
到目前为止,我已经尝试传递一个空数组,以及一个现有数组的副本,我已经从中弹出了所有值。两者都没有奏效。此外,我尝试将我正在使用的 3 个 useState 调用合并到一个单一的状态对象中,但也遇到了同样的问题。
const Map = ({ activeFilter }) => {
const [map, setMapState] = useState(null);
const [maps, setMapsState] = useState(null);
const [overlays, setOverlays] = useState([]);
useEffect(() => {
// console.log('filter - updated');
drawMapFeatures();
}, [activeFilter]);
useEffect(() => {
// console.log('maps - updated');
drawParks();
drawMapFeatures();
}, [maps]);
const setUpMap = (map, maps) => {
setMapState(map);
setMapsState(maps);
};
const drawMapFeatures = () => {
switch (activeFilter) {
case 'Our Buildings':
clearOverlays();
drawNeighborhoods();
drawBuildings();
break;
case 'Restaurants':
clearOverlays();
drawMarkers(places['RESTAURANTS']);
break;
case 'Grab & Go Food':
clearOverlays();
drawMarkers(places['GRAB & GO FOOD']);
break;
case 'Event Spaces':
clearOverlays();
drawMarkers(places['EVENT SPACES']);
break;
case 'Bars':
clearOverlays();
drawMarkers(places['BARS']);
break;
case 'Cafes + Bakeries':
clearOverlays();
drawMarkers(places['CAFES + BAKERIES']);
break;
case 'Retail':
clearOverlays();
drawMarkers(places['RETAIL']);
break;
case 'Health + Fitness':
clearOverlays();
drawMarkers(places['HEALTH + FITNESS']);
break;
case 'Galleries + Museums':
clearOverlays();
drawMarkers(places['GALLERIES + MUSEUMS']);
break;
case 'Film, Theater And Culture':
clearOverlays();
drawMarkers(places['FILM, THEATER AND CULTURE']);
break;
case 'Bank And Convenience':
clearOverlays();
drawMarkers(places['BANK AND CONVENIENCE']);
break;
default:
break;
}
};
const drawParks = () => {
if (map && maps) {
parks.forEach(park => {
const tempPark = new maps.Polygon({
paths: park,
strokeColor: '#afc47b',
strokeOpacity: '1',
strokeWeight: 1,
fillOpacity: '0.8',
fillColor: '#afc47b'
});
tempPark.setMap(map);
});
} else {
// console.log('maps not setup');
}
};
const drawBuildings = () => {
if (map && maps) {
const buildingsArray = overlays.slice(0);
ourBuildings.forEach(building => {
const tempBuilding = new maps.Polygon({
paths: building.path,
strokeColor: '#369BF7',
strokeOpacity: '1',
strokeWeight: 0.5,
fillOpacity: '1',
fillColor: '#369BF7'
});
const tempMarker = new maps.Marker({
position: building.markerPos,
icon: { url: building.markerImg, scaledSize: new maps.Size(90, 60), anchor: new maps.Point(45, 30) }
});
tempBuilding.setMap(map);
tempMarker.setMap(map);
buildingsArray.push(tempBuilding);
buildingsArray.push(tempMarker);
});
if (overlays !== buildingsArray) {
// console.log('buildings');
setOverlays(buildingsArray);
}
}
};
const drawMarkers = data => {
const markersArray = overlays.slice(0);
if (map && maps) {
Object.keys(data).forEach(key => {
const tempMarker = new maps.Marker({
icon: {
path: 'M0,4a4,4 0 1,0 8,0a4,4 0 1,0 -8,0',
fillColor: '#369bf7',
fillOpacity: 0.95,
scale: 1.5,
strokeColor: '#000000',
strokeWeight: 1,
anchor: new maps.Point(-1, 4),
labelOrigin: new maps.Point(4, 15)
},
position: data[key].position,
label: { color: '#000000', fontWeight: 'bold', fontSize: '12px', text: data[key].name }
});
tempMarker.setMap(map);
markersArray.push(tempMarker);
});
}
if (overlays !== markersArray) {
// console.log('markers');
setOverlays(markersArray);
}
};
const drawNeighborhoods = () => {
if (map && maps) {
const neighborhoodArray = overlays.slice(0);
neighborhoodOverlays.forEach(neighborhood => {
const tempNeighborhood = new maps.Polygon({
paths: neighborhood.path,
strokeColor: '#369BF7',
strokeOpacity: 0,
fillOpacity: 0,
strokeWeight: 0,
fillColor: '#369BF7',
zIndex: 100
});
maps.event.addListener(tempNeighborhood, 'mouseover', function() {
this.setOptions({ fillOpacity: '0.5' });
});
maps.event.addListener(tempNeighborhood, 'mouseout', function() {
this.setOptions({ fillOpacity: '0' });
});
tempNeighborhood.setMap(map);
neighborhoodArray.push(tempNeighborhood);
});
if (overlays !== neighborhoodArray) {
// console.log('neighborhoods');
// console.log(neighborhoodArray.length);
setOverlays(neighborhoodArray);
}
}
};
const clearOverlays = () => {
if (overlays.length > 0) {
const overlaysCopy = overlays.slice(0);
// debugger;
while (overlaysCopy.length > 0) {
const overlay = overlaysCopy.pop();
overlay.setMap(null);
}
// console.log('clear');
// console.log(overlaysCopy.length);
setOverlays(overlaysCopy);
// console.log('overlays', overlays.length);
}
};
return (
<MapContainer>
<GoogleMapReact
bootstrapURLKeys={{ key: 'AIzaSyBSsLXxJ5NSrSgFjFW7U5hxmGyHnE1po88' }}
defaultCenter={{
lat: 40.726,
lng: -74.006
}}
defaultZoom={16}
options={mapOptions}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) => setUpMap(map, maps)}
/>
</MapContainer>
);
};
export default Map;
理想情况下,当使用空数组调用 setOverlays 时,覆盖状态将重置为默认值。
解决方案
我已经确定有太多的 setState 操作发生得太近了。为了解决这个问题,我重构了一个类组件,这样我就可以使用 this.setState 和可选的第二个参数以程序方式清除状态并重置。
推荐阅读
- python - 如何在覆盖现有数据的同时将 df 写入工作表?
- python - 如何检查输入字符串是否包含特定字母并且在Python中可以被3整除
- python - 在带有 Python 的 Azure 函数中使用 DefaultAzureCredential()
- javascript - 如何获取动态输入字段的值并在 Django 视图中处理它们
- sql - 在 SQL Server 中高效更新
- r - 如何在另一个包中使用 ggplot_add
- c# - 登录 Excel 插件
- marionette - 木偶没有识别雷鸟弹出窗口
- python - python 切片如何在列表中插入新元素?
- python-3.x - 百分比变化公式给出 -% 出乎意料