n3o
n3o

Reputation: 67

Passing data from UseEffect to Chart.js not working

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

Answers (2)

rashid Bik
rashid Bik

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

Nisharg Shah
Nisharg Shah

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

Related Questions