簡體   English   中英

ReactJS 對對象數組使用 setState()

[英]ReactJS Using setState() for an array of objects

我在使用 setStates 時遇到問題。 I stored an array of markers for my Google Map in my state and I am using a for loop to iterate through each marker in order to change the position state of the marker using Google's Geocode API.

這是我的 state:

state = {
    showingInfoWindow: false,  
    activeMarker: {},          
    selectedPlace: {},
    markers: [
      {
        name: "Costco Wholesale",
        address: "9151 Bridgeport Rd, Richmond, BC V6X 3L9",
        position: { lat: 0, lng: 0 },
        placeID: 'ChIJWc2NzuF0hlQRDu0NNhdQCjM'
      } //just trying to get this one to work first before I add in the others
    ],
    busy: []
  };

這是函數(在類中聲明):

findLatLong(){
    for(let i = 0; i < this.state.markers.length; i++){
        Geocode.fromAddress(this.state.markers[i].address).then(
            response => {
              const { lati, lngi } = response.results[0].geometry.location;
              this.state.markers[i].position.setState({lat: lati, lng: lngi})
            }
          );
    }
  }

如您所見,我將同一數組元素中包含的地址傳遞給.fromAddress function,然后使用 setState 將 lat 和 lng 設置為返回值。

我后來在 map 渲染之后但在標記之前調用 function :

<Map
        google={this.props.google}
        zoom={14}
        style={mapStyles}
        initialCenter={{ lat: 49.166590, lng: -123.133569 }}
      >
      {this.findLatLong}    
      {this.state.markers.map((marker, index) => (
        <Marker
          key={index} 
          onClick={this.onMarkerClick}
          name={marker.name}
          position={marker.position}
        />
      ))}

然而,標記的 position state 沒有改變,而是保留為我在初始 state 聲明期間傳遞的填充值。

完整的代碼,如果它有幫助:

import React, { Component } from 'react';
import { Map, GoogleApiWrapper, InfoWindow, Marker } from 'google-maps-react';
import Geocode from 'react-geocode';

const key = '';
Geocode.setApiKey(key);

const mapStyles = {
    width: '100%',
    height: '100%'
};

export class MapContainer extends Component {
  state = {
    showingInfoWindow: false,  
    activeMarker: {},          
    selectedPlace: {},
    markers: [
      {
        name: "Costco Wholesale",
        address: "9151 Bridgeport Rd, Richmond, BC V6X 3L9",
        position: { lat: 0, lng: 0 },
        placeID: 'ChIJWc2NzuF0hlQRDu0NNhdQCjM'
      }
    ],
    busy: []
  };

  findLatLong(){
    for(let i = 0; i < this.state.markers.length; i++){
        Geocode.fromAddress(this.state.markers[i].address).then(
            response => {
              const { lati, lngi } = response.results[0].geometry.location;
              this.state.markers[i].position.setState({lat: lati, lng: lngi})
            }
          );
    }
  }

  componentDidMount() {
    this.getList();
  }

  getList = () => {
    fetch('/api/getList')
    .then(res => res.json())
    .then(percent => this.setState({ busy: percent }))
  }

  onMarkerClick = (props, marker, e) =>
  this.setState({
    selectedPlace: props,
    activeMarker: marker,
    showingInfoWindow: true
  });

  onClose = props => {
    if (this.state.showingInfoWindow) {
      this.setState({
        showingInfoWindow: false,
        activeMarker: null
      });
    }
  };

  render() {
    return (
      <Map
        google={this.props.google}
        zoom={14}
        style={mapStyles}
        initialCenter={{ lat: 49.166590, lng: -123.133569 }}
      >
      {this.findLatLong}    
      {this.state.markers.map((marker, index) => (
        <Marker
          key={index} 
          onClick={this.onMarkerClick}
          name={marker.name}
          position={marker.position}
        />
      ))}

        <InfoWindow
          marker={this.state.activeMarker}
          visible={this.state.showingInfoWindow}
          onClose={this.onClose}
        >
          <div>
            <h4>{this.state.selectedPlace.name}</h4>
            <h4>{this.state.busy}</h4>
          </div>
        </InfoWindow>
      </Map>
    );
  }
}

先感謝您!

嘗試修復#1

.then(
            response => {
              const { lati, lngi } = response.results[0].geometry.location;
              this.setState(oldState => {
                const newMarkers = [oldState.markers];
                const modifiedMarker = newMarkers[i];
                modifiedMarker.lat = lati;
                modifiedMarker.lng = lngi;
                return {oldState, markers: [newMarkers]};
//How do i implement the modifiedMarkers?
            })

更新

實際上,最好只對 state 進行一次變異而不是在循環內

findLatLong(){
    const newMarkers = [...this.state.markers]
    for(let i = 0; i < this.state.markers.length; i++){
      Geocode.fromAddress(this.state.markers[i].address).then(
        response => {
          const { lati, lngi } = response.results[0].geometry.location;
          newMarkers[i].position.lat = lati; 
          newMarkers[i].position.lng = lngi;
        }
      );
    }

    this.setState(oldState => {
      return { ...oldState, markers: [...newMakers] };
    });
}

這不是你改變 state 的方式,它應該是這樣的:

    this.setState(oldState => {
      const newMakers = [...oldState.makers];
      const modifiedElement = newMakers[i];
      modifiedElement.lat = lati;
      modifiedElement.lng = lngi;
      return { ...oldState, makers: [...newMakers] };
    });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM