ReactJS - TypeError: Cannot read property '0' of undefined

Viewed 18330

I'm trying to make a weather app in order to learn some ReactJS.

I called the OpenWeatherMap API using this fetch in a componentDidMount method inside of my WeatherCard component.

constructor() {
    super()
    this.state = {
        weatherData: {}
    }
}

componentDidMount() {
    fetch('//api.openweathermap.org/data/2.5/weather?q=Calgary,ca&APPID=XXX')
    .then(response => response.json())
    .then(data => {
        this.setState({
            weatherData: data
        })
    })
}

Here's a sample JSON output of the above call (given a valid API key):

enter image description here

I get this error message whenever I want to access a weather property:

TypeError: Cannot read property '0' of undefined

... and I access it like this:

this.state.weatherData.weather[0].main

Here is also my render method if it helps with the problem:

render() {
    return (
        <div>
            {this.state.weatherData.weather[0].main}
        </div>
    )
}

Does anyone know what might be the problem I'm running into? Thanks a lot!

4 Answers

On the first render the request has not yet started, and therefore there is no data yet, you need to have a loading boolean or just check if the data is already loaded before trying to access it.

render() {
    if (!this.state.weatherData.weather) {
        return <span>Loading...</span>;
    }

    return (
        <div>
            {this.state.weatherData.weather[0].main}
        </div>
    )
}

When are you trying to access it?

Can you try this:

render() {
    return (
        <div>
            {this.state.weatherData.weather ? this.state.weatherData.weather[0].main : null}
        </div>
    )
}

It's possible that the render() method is trying to access this.state.weatherData before the data finishes fetching. Try using an inline if to display only when the data is there:

<div>
  {this.state.weatherData &&
    <p>{this.state.weatherData.weather[0].main}</p>
  }
</div>

You have to consider that this.state.weatherData.weather might be undefined or null.

Should try this :

{this.state.weatherData.weather ? this.state.weatherData?.weather[0].main : null}
Related