Reputation: 1027
I have to pass data from MyWeather to MyWeatherData and it occurs that props does not pass into child component, when I use componentDidMount in MyWeatherData. Now I'm using componentDidUpdate in MyWeatherData and it works, but it produces an error: Can only update a mounted or mounting component. Please check the code for the ... component. Does anybody knows how to correct this?
When I pass: <MyWeatherData lat="53.0038" lon="20.0458"/>
it works with ComponentDidMount.
import React, {Component} from "react";
import MyWeatherData from "./MyWeatherData";
export default class MyWeather extends Component {
constructor() {
super();
this.state = {
latitude: "",
longitude: ""
}
this.getMyLocation = this
.getMyLocation
.bind(this)
}
componentDidMount() {
this.getMyLocation()
}
getMyLocation() {
const location = window.navigator && window.navigator.geolocation
if (location) {
location.getCurrentPosition(pos => {
this.setState({latitude: pos.coords.latitude, longitude: pos.coords.longitude})
}, (error) => {
this.setState({latitude: 'err-latitude', longitude: 'err-longitude'})
})
}
}
render() {
const {latitude, longitude} = this.state;
return (
<div>
<MyWeatherData lat={latitude} lon={longitude}/>
</div>
)
}
}
import React, {Component} from "react";
import axios from "axios";
export default class MyWeatherData extends Component {
constructor() {
super();
this.state = {
descriptionMain: "",
description: "",
temperature: null,
weatherIcon: "",
name: ""
}
}
componentDidUpdate = () => {
this.getMyWeather();
}
getMyWeather = () => {
const lat = this.props.lat;
const lon = this.props.lon;
const API_KEY = "e6f4d816d3ade705ec1d8d9701b61e14";
const weatherURL = `https://api.openweathermap.org/data/2.5/weather?APPID=${API_KEY}&units=metric&lat=${lat}&lon=${lon}`;
axios
.get(weatherURL)
.then(res => {
this.setState({descriptionMain: res.data.weather[0].main, description: res.data.weather[0].description, temperature: res.data.main.temp, weatherIcon: res.data.weather[0].icon, name: res.data.name});
})
.catch(error => {
console.log(error);
});
}
render() {
const {descriptionMain, description, temperature, weatherIcon, name} = this.state;
return (
<div>
<h2>Weather for: {name}</h2>
<h4>Sky: {description}</h4>
<h5>Description: {descriptionMain}</h5>
<span className="temperature">{temperature}
°C</span>
{weatherIcon
? (<img
src={`http://openweathermap.org/img/w/${weatherIcon}.png`}
alt={`${description}`}/>)
: null}
</div>
)
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Upvotes: 3
Views: 1729
Reputation: 281656
When getting the information in componentDidMount in the childComponent, you props are passed but since the componentDidMount of the parent is not run by that time the updated props are not available, you should add that part of the code in componentWillReceiveProps
which is executed whenever the props change or the parent component rerenders
import React, {Component} from "react";
import MyWeatherData from "./MyWeatherData";
export default class MyWeather extends Component {
constructor() {
super();
this.state = {
latitude: "",
longitude: ""
}
this.getMyLocation = this
.getMyLocation
.bind(this)
}
componentDidMount() {
this.getMyLocation()
}
getMyLocation() {
const location = window.navigator && window.navigator.geolocation
if (location) {
location.getCurrentPosition(pos => {
this.setState({latitude: pos.coords.latitude, longitude: pos.coords.longitude})
}, (error) => {
this.setState({latitude: 'err-latitude', longitude: 'err-longitude'})
})
}
}
render() {
const {latitude, longitude} = this.state;
return (
<div>
<MyWeatherData lat={latitude} lon={longitude}/>
</div>
)
}
}
import React, {Component} from "react";
import axios from "axios";
export default class MyWeatherData extends Component {
constructor() {
super();
this.state = {
descriptionMain: "",
description: "",
temperature: null,
weatherIcon: "",
name: ""
}
}
componentWillReceiveProps(nextProps){
if(nextProps.lat !== this.props.lat || nextProps.lon !== this.props.lon) {
this.getMyWeather(nextProps);
}
}
getMyWeather = (props) => {
const lat = props.lat;
const lon = props.lon;
const API_KEY = "e6f4d816d3ade705ec1d8d9701b61e14";
const weatherURL = `https://api.openweathermap.org/data/2.5/weather?APPID=${API_KEY}&units=metric&lat=${lat}&lon=${lon}`;
axios
.get(weatherURL)
.then(res => {
this.setState({descriptionMain: res.data.weather[0].main, description: res.data.weather[0].description, temperature: res.data.main.temp, weatherIcon: res.data.weather[0].icon, name: res.data.name});
})
.catch(error => {
console.log(error);
});
}
render() {
const {descriptionMain, description, temperature, weatherIcon, name} = this.state;
return (
<div>
<h2>Weather for: {name}</h2>
<h4>Sky: {description}</h4>
<h5>Description: {descriptionMain}</h5>
<span className="temperature">{temperature}
°C</span>
{weatherIcon
? (<img
src={`http://openweathermap.org/img/w/${weatherIcon}.png`}
alt={`${description}`}/>)
: null}
</div>
)
}
}
Upvotes: 2