Вы не должны иметь асинхронных вызовов функций в вашем методе рендеринга.Наилучшим местом для асинхронных вызовов является 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
является thunk, вам нужно передать его dispatch
.Измените вашу mapDispatchToProps
переданную функцию на connect
следующим образом:
const connectVaca = connect(
state => ({vacations: state}),
dispatch => {
return { getVacations: () => dispatch(getVacations()) }
}
)(GoogleMaps);
Edit2: Это связано с тем фактом, что реакция запускает начальный render()
вызов сразу после перехода на страницу.загружен.Затем, как только ваш компонент смонтирован, вызывается componentDidMount
.В componentDidMount
вы запускаете асинхронную функцию getVacations
.Поскольку вы не ожидаете завершения вызова API в getVacations
, создание маркера происходит без загрузки отпуска.Всякий раз, когда вы посещаете новую вкладку и возвращаетесь к своему приложению, render
происходит снова с загруженными отпусками от предыдущего вызова API, поэтому они появляются.
Попробуйте вернуть обещание из вашего действия 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
:
componentDidMount = () => {
this.props.getVacations().then(() => {
// Place coordinates, your Promise.all call, and your setState call here
});
}