简体   繁体   English

ReactJS 对对象数组使用 setState()

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

I am having trouble using setStates.我在使用 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. 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.

Here is my state:这是我的 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: []
  };

Here is the function(declared inside the class):这是函数(在类中声明):

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})
            }
          );
    }
  }

As you can see, I am passing the address contained in the same array element into the.fromAddress function and then using setState to set the lat and lng to the returned value.如您所见,我将同一数组元素中包含的地址传递给.fromAddress function,然后使用 setState 将 lat 和 lng 设置为返回值。

I later call the function after the map renders but before the markers do:我后来在 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}
        />
      ))}

However marker's position state is not changing and is instead remaining as the filler values I passed during the initial state declaration.然而,标记的 position state 没有改变,而是保留为我在初始 state 声明期间传递的填充值。

Full code if it helps:完整的代码,如果它有帮助:

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>
    );
  }
}

Thank you in advance!先感谢您!

Attempt to fix #1尝试修复#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?
            })

UPDATE更新

Actually it is better if you mutate the state just once and not inside the loop实际上,最好只对 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] };
    });
}

That's no how you mutate the state, it should be something like this:这不是你改变 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