使用不更新数组的状态设置器方法



我正在使用 react 钩子在 react 中编写一个谷歌地图组件,我将状态中的谷歌地图标记和多边形数组存储为称为覆盖的数组。当我从地图中清除叠加层时,我用空数组调用 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;

理想情况下,当使用空数组调用 setOverlayer 时,覆盖状态将重置为默认值。

我已经确定有太多的setState操作发生得太近了。为了解决这个问题,我重构到一个类组件中,这样我就可以使用 this.setState 和可选的第二个参数来程序化地清除状态并重置。

尝试更改:

  const [map, setMapState] = useState(null);
  const [maps, setMapsState] = useState(null);

  const [mapState, setMapState] = useState(null);
  const [mapsState, setMapsState] = useState(null);

相关内容

  • 没有找到相关文章