Reputation: 67
I'm trying to use the useEffect() hook. I pull data from my API, parse it in useEffect() and store it into temperature using setTemperature(temp). However, when I pass temperature to a chart.js field, it doesn't read in the array. Why is this? I've statically added an array to the chart.js field to test and it works. So I'm pretty sure it doesn't have to do with the chart.js side.
const [temperature, setTemperature] = useState([]);
const [humidity, setHumidity] = useState([]);
const [timestamp, setTimestamp] = useState([]);
useEffect(function() {
async function getData() {
try{
let response = await axios.get('/api/sensorData');
let temp = [];
let hum = [];
let time = [];
response.data.query.forEach((item)=>{
Object.entries(item).forEach(([key, val]) => {
if (key === 'humidity'){
hum.push(val);
}else if (key === 'temperature'){
temp.push(val);
}else{
time.push(val);
}
});
});
console.log(temp)
setTemperature(temp);
setHumidity(hum);
setTimestamp(time);
}catch(error){
console.log('error', error);
}
}
getData();
}, []);
return(
<div className="container">
<h2> Environmental Stats </h2>
<br/>
<h3> Temperature </h3>
<LineChart
labels={['January', 'February', 'March',
'April', 'May','June']}
datasets={[
{
label: 'Temperature',
fill: false,
lineTension: 0.5,
backgroundColor: 'rgba(75,192,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 1.5,
data: temperature
}
]}
/>
);
Upvotes: 0
Views: 693
Reputation: 9
This is because of DOM rendering in react the chart most wait until data is fetched the solution is to add a loading... state.
my code `
const [assets, setAssets] = useState({});
const [chartData, setChartData] = useState();
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`http://localhost:4000/api/user/content/${#####}`)
.then((res)=> res.json())
.then(({content, assets}) => {
setAssets(assets)
setLoading(false)
})
.catch(err => err);
setChartData({
labels: ['income', 'expens'],
datasets: [{data: [assets.income, assets.expens]} ]
})
}, []);
return (
<div className="App">
<div className="chart-container">
<h2 style={{ textAlign: "center" }}>Pie Chart</h2>
{ loading ? (<h1>loading...</h1>):(
<>
<Pie
data={chartData}
options={{
plugins: { title:
{ display: true, text: "message" }}
}}
/>
</>
)
}
</div>
</div>
);
`
Upvotes: 0
Reputation: 19652
Do it like this
Problem
you are calling API and its async operation that's why you need to wait for some time to load that function and that's why you need one loading flag to check async function calling finished or not
const [temperature, setTemperature] = useState([]);
const [humidity, setHumidity] = useState([]);
const [timestamp, setTimestamp] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(function() {
async function getData() {
try{
let response = await axios.get('/api/sensorData');
let temp = [];
let hum = [];
let time = [];
response.data.query.forEach((item)=>{
Object.entries(item).forEach(([key, val]) => {
if (key === 'humidity'){
hum.push(val);
}else if (key === 'temperature'){
temp.push(val);
}else{
time.push(val);
}
});
});
console.log(temp)
setTemperature(temp);
setHumidity(hum);
setTimestamp(time);
setLoading(false);
}catch(error){
console.log('error', error);
}
}
getData();
}, []);
if (loading) return <p>Loading...</p>
return(
<div className="container">
<h2> Environmental Stats </h2>
<br/>
<h3> Temperature </h3>
<LineChart
labels={['January', 'February', 'March',
'April', 'May','June']}
datasets={[
{
label: 'Temperature',
fill: false,
lineTension: 0.5,
backgroundColor: 'rgba(75,192,192,1)',
borderColor: 'rgba(0,0,0,1)',
borderWidth: 1.5,
data: temperature
}
]}
/>
);
Upvotes: 1