ReactJS Использование setState () для массива объектов - PullRequest
0 голосов
/ 19 июня 2020

У меня проблемы с использованием setStates. Я сохранил массив маркеров для моей карты Google в своем состоянии, и я использую for l oop для перебора каждого маркера, чтобы изменить состояние положения маркера с помощью Google Geocode API.

Здесь это мое состояние:

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, а затем с помощью setState установить lat и lng на возвращаемое значение.

Позже я вызываю функцию после отрисовки карты, но до того, как это сделают маркеры: состояние позиции маркера не меняется и вместо этого остается в качестве значений заполнителя, которые я передал во время объявления начального состояния.

Полный код, если это помогает:

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

1 Ответ

1 голос
/ 19 июня 2020

ОБНОВЛЕНИЕ

На самом деле лучше, если вы измените состояние только один раз, а не внутри l oop

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

Это не то, как вы мутируете состояние, это должно получиться примерно так:

    this.setState(oldState => {
      const newMakers = [...oldState.makers];
      const modifiedElement = newMakers[i];
      modifiedElement.lat = lati;
      modifiedElement.lng = lngi;
      return { ...oldState, makers: [...newMakers] };
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...