chinds chinds - 2 months ago 15
React JSX Question

accessing object attributes in the react render method

I have written a small react component which fetches some data from the open weather api. The fetch succeeds and I can get a json object in the response.

I then save this response to the components state using

this.setState({})


And the react dev tools show the forecast object is infact saved in state.

However when I come to rendering any of the data i always get an error stating `cannot read property 'forecast' of null.

Below is the react component and a screen shot of the object itself.

export default class Weather extends Component {
getWeather () {
var self = this;

fetch('http://api.openweathermap.org/data/2.5/weather?zip=sl44jn,uk&units=metric&APPID=ed066f80b6580c11d8d0b2fb71691a2c')
.then (function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' + response.status);
return;
}

response.json().then(function(data) {
self.setWeather(data);
});
})

.catch (function (err) {
console.log('Fetch Error :-S', err);
});
}

setWeather (forecast) {
console.log(forecast);
this.setState({
forecast: forecast.name
})
}

componentWillMount () {
this.getWeather();
}

componentDidMount () {
// window.setInterval(function () {
// this.getWeather();
// }.bind(this), 1000);
}

render() {
return (
<h1>{this.state.forecast}</h1>
)
}
}


And this is the data object itself, right now I am simply trying to access the name attribute.

enter image description here

Answer

Looks like you forgot couple of things, in order to a Component to setState you need to bind it to this preferably in the constructor. You also need to set the initial state, in your case an empty object, and you can save the whole response in the object and access just the parts you want. have a look:

export default class Weather extends Component {

constructor() {
    super();
    this.state = {
      forecast: {}
    };
    this.setWeather = this.setWeather.bind(this);
  }

  getWeather () {
    let self = this;
    fetch('http://api.openweathermap.org/data/2.5/weather?zip=sl44jn,uk&units=metric&APPID=ed066f80b6580c11d8d0b2fb71691a2c')
      .then (function (response) {
        if (response.status !== 200) {
          console.log('Looks like there was a problem. Status Code: ' + response.status);
          return;
        }
        response.json().then(function(data) {  
        self.setWeather(data);
      });
    })
    .catch (function (err) {  
      console.log('Fetch Error :-S', err);
    });
  }

  setWeather (forecast) {
    this.setState({
      forecast: forecast
    });
  }

  componentWillMount() {
    this.getWeather();
  }

  render() {
    const { forecast } = this.state;
    return (
      <h1>{forecast.name}</h1>
    )
  }
}
Comments