Natalia
Natalia

Reputation: 1027

ComponentDidMount does not work - props do not pass to child component

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

Answers (1)

Shubham Khatri
Shubham Khatri

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

Related Questions