Can't access the nested objects but can render the non-nested ones from API (using React hooks) - reactjs

I'm a bit stumped on this problem I encountered trying to render the data from an API. Weird thing is I successfully fetched the data and I can render the values of properties in the array but the moment it becomes a nested property within an array it returns undefined. Do you by any chance know why?
location[0] + '&lon=' +
location[1] + '&APPID=8e6150cf719d58fc8062d507eaba92c0'
const [data, loading] = useFetch(url);
console.log(data.main.temp) // returns undefined
console.log(data.name) // logs name
The useFetch() is the following:
useEffect(() => {
async function fetchUrl() {
const response = await fetch(url);
const json = await response.json();
setData(json);
setLoading(false);
}
fetchUrl();
}, [url]);
return [data, loading];
}
export { useFetch };
The error message is:
TypeError: Cannot read property 'temp' of undefined
Data fetched looks like this:
{
"coord": {
"lon": 2.18,
"lat": 41.42
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01n"
}
],
"base": "stations",
"main": {
"temp": 293.81,
"pressure": 1013,
"humidity": 77,
"temp_min": 292.04,
"temp_max": 294.82
},
"visibility": 10000,
"wind": {
"speed": 2.6,
"deg": 120
},
"clouds": {
"all": 0
},
"dt": 1561061585,
"sys": {
"type": 1,
"id": 6414,
"message": 0.0074,
"country": "ES",
"sunrise": 1561004254,
"sunset": 1561058875
},
"timezone": 7200,
"id": 3124932,
"name": "el Clot",
"cod": 200
}

Related

TypeError: Cannot read property 'temp' of undefined

I am trying to access data from OpenWeather API and it has nested objects and I keep getting the error trying to access data in these nested objects. I can access values from the parent object but no from nested ones.
this is me passing data to the component.
const Card = ({ cardRef }) => {
const [data, setData] = useState({});
useEffect(() => {
setData({ ...cardRef });
console.log(data.main.temp);
}, [cardRef]);
I can access data.main but not data.main.temp
below in the data being passed
{
"coord": {
"lon": -0.2,
"lat": 5.56
},
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}
],
"base": "stations",
"main": {
"temp": 304.15,
"feels_like": 304.86,
"temp_min": 304.15,
"temp_max": 304.15,
"pressure": 1011,
"humidity": 66
},
"visibility": 10000,
"wind": {
"speed": 7.2,
"deg": 190
},
"rain": {
"1h": 0.29
},
"clouds": {
"all": 20
},
"dt": 1607092023,
"sys": {
"type": 1,
"id": 1126,
"country": "GH",
"sunrise": 1607061413,
"sunset": 1607103947
},
"timezone": 0,
"id": 2306104,
"name": "Accra",
"cod": 200
}
Since setData is the asynchronous method, you can't get the updated value of data immediatley after setData.
const Card = ({ cardRef }) => {
const [data, setData] = useState({});
useEffect(() => {
setData({ ...cardRef });
console.log(data.main.temp); // data is still the old value which is initial empty {} value, so `data.main` is undefined and `data.main.temp` will be error.
}, [cardRef]);
You should get it inside useEffect with adding a data dependency.
useEffect(() => {
if (data.main) { // Make sure that you need to check if `data.main` is not undefined before referring `data.main.temp`.
console.log(data.main.temp);
}
}, [data]);

ReactJS data from API

Hello guys when i'm running this code in ReactJS
const callApi = async () => {
const response = await axios.get('http://api.openweathermap.org/data/2.5/weather?q=London&units=metric&appid=mykey');
setWeather(response)
}
i can get to console.log(weather.data) but when i try to get console.log(weather.data.main)
i get this error TypeError: Cannot read property 'main' of undefined i tried to parse that data to JSON but that didnt work either.
Here you can see that this object has this property:
{
"coord": {
"lon": -0.13,
"lat": 51.51
},
"weather": [
{
"id": 804,
"main": "Clouds",
"description": "overcast clouds",
"icon": "04n"
}
],
"base": "stations",
"main": {
"temp": 12.43,
"feels_like": 7.81,
"temp_min": 11.67,
"temp_max": 13,
"pressure": 1010,
"humidity": 62
},
.....other items
}
Thank you for all answers.
Sometimes during the first render data isn't defined yet so use:
console.log(weather.data?.main)
and works like a if(data)

Extracting images data from Promise (ReactJS and Axios)

How do I get access to data stored as a Promise[] in ES6 array? I am loading an array from the backend and each object has a url for the image. So in order to render the image I have to async/await fetch the images for each object. Instead of returning a Base64 image, I get I promise with the image embeded deep in the promise. I need a way to read the image data. See image below for return object structure.
Please note that i use axios in the background and NOT the Fetch API
Below are the functions and service methods used to load the list and then the images in 2 steps.
1.1 Axios service method
listAllItems() {
return axios.get(API_URL + "docman/items/list/all");
}
1.2 ReactJS main function
async componentDidMount() {
try {
const items = await DocmanService.listAllItems();
const itemsData = items.data;
const data = await itemsData.map(item => {
const image = this.loadImage(item.image);
return { ...item, image: image }
})
this.setState({ items: data });
} catch (e) {
console.log(e);
}
}
2.1 Axios images service method
loadImage = (url) => {
return axios.get(API_URL + url, { responseType: 'arraybuffer' });
}
2.2 ReactJS image loader function
async loadImage(imageUrl) {
try {
return await ImageService.loadImage(imageUrl)
} catch (e) {
return '';
}
}
3.1 Json list fetched from backend
[
{
"id": "1",
"uuid": "1c0a33af-4e78-4823-b84e-f3b5464db2af",
"identifier": "EN ISO 8402",
"title": "EN ISO 8402 Quality Management - Vocabulary",
"folder": "e347fef9-0a76-4e62-b7f2-c78e9f88355b",
"media": "FILE",
"path": "document/id/105",
"image": "image/id/106",
"format": "PDF",
"authors": "",
"publishers": "",
"created": "2020-09-22T14:56:31.316+00:00",
"published": null,
"version": "1994",
"status": null
},
{
"id": "2",
"uuid": "16a0e658-b444-4b60-bf18-ba2786d5fb00",
"identifier": "ISO 14001",
"title": "ISO 14001 Environmenatl Management Systems - Requirements with Guidance for Use",
"folder": "e347fef9-0a76-4e62-b7f2-c78e9f88355b",
"media": "FILE",
"path": "document/id/107",
"image": "image/id/108",
"format": "PDF",
"authors": "",
"publishers": "",
"created": "2020-09-22T14:56:31.659+00:00",
"published": null,
"version": "2004",
"status": null
},
-
-
]
try doing image.then((data) => { // console.log(data) })
When you setState you are setting the new state with a list of objects with an image value that is a promise. Shouldn't you update the state only when at least one of the promise resolved to a real image?
Couldn't you do something like
this.loadImage(item.image).then((imageData=>setState(appropriate State)))?

REACT AXIOS not showing nested items

I am trying to read Midnight item in the below response
assuming it is data.timings.Midnight , but it is not showing in my react.
Is there away iterate through these nested items and show them ?
HTTP/1.1 200 OK
{
"code": 200,
"status": "OK",
"data": [{
"timings": {
"s": "03:57",
"Ss": "05:46",
"Dh": "12:59",
"Asr": "16:55",
"Sun": "20:12",
"Mag": "20:12",
"Is": "22:02",
"DATAIMintested": "03:47",
"Midnight": "00:59"
},
"date": {
"readable": "24 Apr 2014",
"timestamp": "1398332113",
"gregorian": {
"date": "15-05-2018",
"format": "DD-MM-YYYY",
"day": "15",
"weekday": {
"en": "Tuesday"
},
"month": {
"number": 5,
"en": "May",
},
"year": "2018",
"designation": {
"abbreviated": "AD",
"expanded": "Domini",
},
You are getting an array in the response. I assume you want to access the zeroeth element in the array. You can do it as below
Axios.get('<your url>')
.then(res => {
const responseData = res.data;
if(responseData && responseData.length > 0){
const midnight = responseData[0].timings.Midnight;
...
...
}
})
.catch(...)
I am guessing it is an array of objects, try to access the array's elements using indexes.Something like
axios.get(url).then(resp => {
console.log(resp.data[0].timings.Midnight);
});

I am trying to call Weather API using React and Axios I am trying to console.log the result but its saying the undefined... :(

When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
class App extends Component {
state = {
content: [{ coord: "" }, { base: "" }]
};
componentDidMount() {
axios
.get(
"https://api.openweathermap.org/data/2.5/weather?q=berlin&appid=240ef553958220e0d857212bc790cd14"
)
.then(res => {
this.setState({
content: [
{
coord: res.data.coord
},
{ base: res.data.base }
]
});
});
}
render() {
console.log(this.state.content.coord);
return (
<div className="App center">
<h2 className="blue-text">Weather App</h2>
<div></div>
<Weather />
</div>
);
}
}
export default App;
JSON endpoint goes here....
{
"coord": {
"lon": 13.41,
"lat": 52.52
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04n"
}
],
"base": "stations",
"main": {
"temp": 276.88,
"feels_like": 268.47,
"temp_min": 275.37,
"temp_max": 278.15,
"pressure": 994,
"humidity": 80
},
"visibility": 10000,
"wind": {
"speed": 9.3,
"deg": 240,
"gust": 14.4
},
"clouds": {
"all": 75
},
"dt": 1580260557,
"sys": {
"type": 1,
"id": 1275,
"country": "DE",
"sunrise": 1580280826,
"sunset": 1580312685
},
"timezone": 3600,
"id": 2950159,
"name": "Berlin",
"cod": 200
}
As content is an array type you can access coord or base directly. Instead change it to an object or access it based on array index like this.
this.state.content[0].coord / this.state.content[1].base
If you change content to object type you can access coord or base directly as i did it here
sample code:
state = {
content: { coord: "", base: "" }
};
after request fetch you can update state something like this.
this.setState({
content: { coord: res.data.coord, base: res.data.base }
});
You can make your state look like below which make reading and accessing the data easier.
state = {
content: {
coord: "",
base: "",
},
}
and your setState like below:
this.setState({
content: {
coord: res.data.coord,
base: res.data.base
}
})

Resources