简体   繁体   中英

Cant use dot or bracket notation to access keys or data in json/javascript object saved to state after fetch

I'm currently learning react-native after some time on react and have come across a weird occurrence I don't understand.

I am fetching a JSON file from an API and saving it in my state. Elsewhere in the file when I try to access values with dot and bracket notation it breaks my code saying 'undefined is not an object' and the value of this constant is indeed undefined. But the strange part is if I then use setState inside my fetch and dot/bracket notation to get a specific value it works fine. But I want to have this functionality else whereas I will be mapping through the data a lot.

I read I might need to use JSON.parse but could work out where to place this in my fetch and it returned an error inside a console.log.

JSON.stringify works but then I just have a huge string so have lost the power of an object.

Dot and bracket notation tried it all as I say works inside fetch perfectly but when calling the state

First setting the state into a const then passing this into the console.log, no difference.

fetchWeather(lat = 15, lon = 85) {
    fetch(
      `http://api.openweathermap.org/data/2.5/forecast?lat=${lat}&lon=${lon}&APPID&APPID=${API_KEY}&units=metric`,
    )
      .then(res => res.json())
      .then(json => {
        this.setState({
          forecast: json.list,
          temp: json.list[0].main.temp // WORKS! returns temp eg 25.34
          isLoading: false,
        });
      })
      .catch(error => console.log(error));
}
console.log(this.state.forecast[0]); //works I get the first index of an array of objects but has and added key Object {}
console.log(this.state.forecast[0].main.temp); //undefined
console.log(this.state.forecast[0]['main']['temp']); //undefined

I see this Object {} showing up in the console but maybe this isn't anything to worry about?

eg.

"main": Object {
    "grnd_level": 1008.34,
    "humidity": 54,
    "pressure": 1013.04,
    "sea_level": 1013.04,
    "temp": 28.1,
    "temp_kf": 4.74,
    "temp_max": 28.1,
    "temp_min": 23.36,
},

should be,

"main": {
    "grnd_level": 1008.34,
    "humidity": 54,
    "pressure": 1013.04,
    "sea_level": 1013.04,
    "temp": 28.1,
    "temp_kf": 4.74,
    "temp_max": 28.1,
    "temp_min": 23.36,
  },

I expect from console.log(this.state.forecast[0].main.temp) return 23.45 and console.log(this.state.forecast[0]['main']) return

"grnd_level": 1008.34,
"humidity": 54,
"pressure": 1013.04,
"sea_level": 1013.04,
"temp": 28.1,
"temp_kf": 4.74,
"temp_max": 28.1,
"temp_min": 23.36,

https://samples.openweathermap.org/data/2.5/forecast?lat=35&lon=139&appid=b6907d289e10d714a6e88b30761fae22

https://openweathermap.org/forecast5

I assume that this part in your Gist is causing the error:

if (this.state.forecast !== {}) {
  console.log(this.state.forecast[0].main);
}

You're initializing your state.forecast with an empty object {} and try to check for that.

Judging from the data structure perspective, this is a bit misleading, because the actual content will be an array.

More importantly, though, the two variables are compared by identity and the right operand is an empty object newly created on the stack every time render is called and can never be equal to whatever is in forecast . Thus, the condition always evaluates to true which leads to an attempt to access data which is not yet present at the first render.

As you're only waiting for forecast to be filled through the fetch call, and the content of forecast is known, it should be sufficient to initialize the state with forecast: null (or not at all) and then check if forecast is set at all (not false , not null , not undefined , not 0, not '' ,...):

if (this.state.forecast) {
  console.log(this.state.forecast[0].main);
}

Or a bit more strict:

if (typeof this.state.forecast === 'object') { // typeof array is also 'object'
  console.log(this.state.forecast[0].main);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM