Cannot fix this error. I receive data (object) from thingspeak.com via fetch method. Then I want to render three values from that object: name, temperature and time. I can see temperature and name but not time. Here is my error in console: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '0'). Any ideas?
import React, { useState, useEffect } from 'react'
const App = () => {
const [channelInfo, setChannelInfo] = useState({});
const [isLoading, setIsLoading] = useState(true);
const [dateWithOffset, setDateWithOffset] = useState(null);
const getThermoData = async () => {
setIsLoading(true);
const response = await fetch(`https://api.thingspeak.com/channels/618304/fields/1.json?results=1`);
const data = await response.json();
setChannelInfo(data);
setIsLoading(false);
timeConverter();
}
const timeConverter = () => {
const channelDate = channelInfo.feeds[0].created_at;
const date = new Date(channelDate);
const timestampWithOffset = date.getTime();
setDateWithOffset(new Date(timestampWithOffset));
}
useEffect(() => {
getThermoData();
}, [])
return (
<div className='card'>
{
isLoading ? <p className='loading'>Loading...</p> : <>
<h5 className='channel-name no-select'>{channelInfo.channel.name}</h5>
<p className='temperature-value no-select'>{channelInfo.feeds[0].field1}</p>
<h5 className='channel-time no-select'>{dateWithOffset}</h5>
</>
}
</div>
)
}
export default App
CodePudding user response:
Calling timeConverter
just after setting the new state with setChannelInfo(data);
will throw you an exception due to 1) Initial channelInfo
value is {}
so there is no .feeds[0].created_at
and 2) calling setChannelInfo
will not update the variable immediately. It will be updated on next render only.
You can switch to useMemo
, add undefined
check, change initial state of channelInfo
to undefined.
import { useState, useEffect, useMemo } from "react";
const App = () => {
const [channelInfo, setChannelInfo] = useState();
const [isLoading, setIsLoading] = useState(true);
const dateWithOffset = useMemo(() => {
if (!channelInfo) return "";
const channelDate = channelInfo.feeds[0].created_at;
const date = new Date(channelDate);
const timestampWithOffset = date.getTime();
return new Date(timestampWithOffset).toString();
}, [channelInfo]);
const getThermoData = async () => {
setIsLoading(true);
const response = await fetch(
`https://api.thingspeak.com/channels/618304/fields/1.json?results=1`
);
const data = await response.json();
setChannelInfo(data);
setIsLoading(false);
};
useEffect(() => {
getThermoData();
}, []);
return (
<div className="card">
{isLoading ? (
<p className="loading">Loading...</p>
) : (
<>
<h5 className="channel-name no-select">{channelInfo.channel.name}</h5>
<p className="temperature-value no-select">
{channelInfo.feeds[0].field1}
</p>
<h5 className="channel-time no-select">{dateWithOffset}</h5>
</>
)}
</div>
);
};
export default App;