useState setter方法不更新数组

时间:2019-06-17 19:40:43

标签: arrays reactjs state react-hooks

我正在使用react钩子在react中编写一个google maps组件,并将状态为google的Maps Markers和Polygons数组存储为名为overlays的数组。当我从地图上清除叠加层时,我使用一个空数组调用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时,叠加层状态将重置为默认值。

2 个答案:

答案 0 :(得分:0)

尝试更改:

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

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

答案 1 :(得分:0)

我确定有太多setState操作发生得太近了。为了解决这个问题,我将其重构为类组件,以便可以使用this.setState和可选的第二个参数来按程序清除状态并重置。