使用Promise.all在Google Maps上放置标记-对象作为React子对象无效(发现:[object Promise])

时间:2018-06-24 19:16:19

标签: javascript reactjs google-maps es6-promise

几天来,我一直在尝试将标记放置在Google地图上的坐标上,但遇到此错误:

对象作为React子对象无效(发现:[object Promise])

因此,我发现可以使用Promise.all来解决此问题,但是在正确执行此操作时遇到了麻烦。我不完全确定应该在组件中的方式和位置。

有人可以帮我吗?

代码如下:

import React, { Component } from "react";
import { Map, InfoWindow, Marker, GoogleApiWrapper } from "google-maps-react";
import Navbar from "./Navbar";
import { connect } from "react-redux";
import { getVacations } from "./redux";
import Geocode from "react-geocode";

class GoogleMaps extends Component {
  constructor() {
    super();
    this.state = {
      coords: []
    }
  }

  componentDidMount = () => {
    this.props.getVacations();
  }

  render() {
    console.log(this.props);

    const coordinates = this.props.vacations.map(coordinate => {
      const convert = Geocode.fromAddress(coordinate.location);
      return convert;
    })

    Promise.all(coordinates).then(locations => {
      const markers = locations.map(place => {
        console.log(place);
        const lat = place.results[0].geometry.location.lat;
        const lng = place.results[0].geometry.location.lng;
        return [
          <Marker
            key={place._id}
            position={
              {
                lat: lat, 
                lng:lng
              }
            }
            animation={2}
          />
        ]
      })
      this.setState({
        coords: markers
      })
    })

    return (
      <div>
        <Navbar />
        <Map
          google={this.props.google}
          zoom={4} 
        >
          {this.state.coords}
        </Map>
      </div>
    )
  }
}

const connectVaca = connect(state => ({vacations: state}), {getVacations})(GoogleMaps);

export default GoogleApiWrapper({
            apiKey: "API KEY HERE"
})(connectVaca)

这是我的getVacations动作和减速器:

export const getVacations = () => {
    return dispatch => {
        axios.get("/vacations").then(response => {
            dispatch({
                type: "GET_VACATIONS",
                vacations: response.data
            })
        }).catch(err => {
            console.log(err);
        })
    }
}

const reducer = (state = [], action) => {
    switch(action.type){
        case "GET_VACATIONS":
            return action.vacations;
        default:
            return state;
    }
}

1 个答案:

答案 0 :(得分:1)

render方法中不应包含异步函数调用。根据react文档,异步调用的最佳位置是componentDidMount

将您的Promise.all调用放入componentDidMount函数中。无论何时安装组件,都会执行此功能。然后,只要调用setState来设置coords,您的组件就会使用更新后的coords值重新呈现。

import React, { Component } from "react";
import { Map, InfoWindow, Marker, GoogleApiWrapper } from "google-maps-react";
import Navbar from "./Navbar";
import { connect } from "react-redux";
import { getVacations } from "./redux";
import Geocode from "react-geocode";

class GoogleMaps extends Component {
  constructor() {
    super();
    this.state = {
      coords: []
    }
  }

  componentDidMount = () => {
    this.props.getVacations();
    const coordinates = this.props.vacations.map(coordinate => {
      const convert = Geocode.fromAddress(coordinate.location);
      return convert;
    })
    Promise.all(coordinates).then(locations => {
      const markers = locations.map(place => {
        console.log(place);
        const lat = place.results[0].geometry.location.lat;
        const lng = place.results[0].geometry.location.lng;
        return (
          <Marker
            key={place._id}
            position={
              {
                lat: lat, 
                lng:lng
              }
            }
            animation={2}
          />
        )
      })
      this.setState({
        coords: markers
      })
    })
  }

  render() {
    return (
      <div>
        <Navbar />
        <Map
          google={this.props.google}
          zoom={4} 
        >
          {this.state.coords}
        </Map>
      </div>
    )
  }
}

const connectVaca = connect(state => ({vacations: state}), {getVacations})(GoogleMaps);

export default GoogleApiWrapper({
            apiKey: "API KEY HERE"
})(connectVaca)

编辑:由于loadVacations是重击,因此您需要将其传递给dispatch。像这样更改传递给mapDispatchToProps的{​​{1}}函数:

connect

Edit2 :它与以下事实有关:页面加载后,react运行初始const connectVaca = connect( state => ({vacations: state}), dispatch => { return { getVacations: () => dispatch(getVacations()) } } )(GoogleMaps); 调用。然后,一旦安装了组件,就会调用render()。在componentDidMount中,运行异步函数componentDidMount。由于您没有等待getVacations中的API调用完成,因此标记创建过程尚未加载任何休假。每当您访问新标签页并返回到您的应用程序时,getVacations就会再次发生,并显示以前的API调用中加载的休假。

尝试从您的操作render返回承诺。然后,每当您在getVacations中调用getVacations时,请将componentDidMount调用链接到then。在getVacations内应放置坐标创建和then调用。然后,我相信您的代码会工作。

Promise.all

然后在您的export const getVacations = () => { return dispatch => { // returning axios.get will return a promise you can chain a then call on return axios.get("/vacations").then(response => { dispatch({ type: "GET_VACATIONS", vacations: response.data }) }).catch(err => { console.log(err); }) } } 函数中:

componentDidMount