'react-chartjs-2 does not show line until window is resized

I'm having this weird bug with my React app with the react-chartjs-2. Chart data does not show correctly until I resize window. Tested on Firefox and Chrome, same result. Data is there, but I don't know if the data is loaded after the render or something. Please, I am student and not an expert, so please explain in detail if you know the solution for my problem. Thank you!

Youtube video of my bug

import React, {Component} from 'react';
import {Line} from 'react-chartjs-2';

const options = {
    title: {
        display: true,
        text: "Chart Title"
    },
    scales: {
        yAxes: [
            {
                ticks: {
                    suggestedMin: 20,
                    suggestedMax: 50
                }
            }
        ]
    }
};

const legend = {
    display: true,
    position: "bottom",
    labels: {
        fontColor: "#323130",
        fontSize: 14
    }
};
class SensorChart extends Component {

    constructor(props) {
        super(props);
        this.chartReference = React.createRef()
        this.state = {
            data : {
                labels: props.labels,
                datasets: [
                    {
                        label: "Humidity",
                        borderColor: "rgb(9,0,192)",
                        data: props.humidity
                    },
                    {
                        label: "Temperature",
                        borderColor: "red",
                        data: props.temperature
                    }
                ]
            }
        }
    }

    componentDidMount() {
        console.log(this.state.data.datasets[0].data)
        console.log(this.state.data.datasets[1].data)
    }


    render() {
        return (
            <div>
                <h5>Line Example</h5>
                <Line ref={this.chartReference} data={this.state.data} legend={legend} options={options}/>
            </div>
        );
    }

}

export default SensorChart;
import React from 'react';
import Icon from '@mdi/react'
import {mdiThermometer, mdiWaterPercent, mdiCalendarRange} from '@mdi/js';
import './SensorData.css';
import SensorChart from "./SensorChart";

function SensorData() {


    const [humi, setHumi] = React.useState("");
    const [temp, setTemp] = React.useState("");
    const [date, setDate] = React.useState("");

    const [labels] = React.useState([]);
    const [humidity] = React.useState([]);
    const [temperature] = React.useState([]);


    function fetchData() {
        fetch('https://myAPIurl/datalist/100')
            .then(response => response.json())
            .then(responseData => {
                setDate(responseData[0].stringTime);
                setHumi(responseData[0].humidity);
                setTemp(responseData[0].temperature);

                for (let i = 0; i < 100; i++) {
                    labels.push(responseData[i].stringTime)
                    humidity.push(responseData[i].humidity)
                    temperature.push(responseData[i].temperature)
                }

            })
    }

    React.useEffect(() => {
        fetchData();
    }, []);


    return (
        <div className="App">
            <h1>Sensor data</h1>

            <h3><Icon path={mdiWaterPercent}/> Humidity: {humi}%</h3>
            <h3><Icon path={mdiThermometer}/>Temperature: {temp}°C</h3>
            <h3><Icon path={mdiCalendarRange}/>Time: {date}</h3>
            <div className="Chart">
                <SensorChart labels={labels} humidity={humidity} temperature={temperature}/>
            </div>
        </div>
    );
}

export default SensorData;

Console logs after site is loaded

 console.log(this.state.data.datasets[0].data)       

 console.log(this.state.data.datasets[1].data)
_chartjs: {…}, push: ƒ, pop: ƒ, shift: ƒ, splice: ƒ, …]0: 371: 372: 353: 354: 355: 366: 387: 388: 409: 4110: 4711: 4312: 4013: 3714: 3615: 3516: 3717: 3618: 3619: 3620: 3621: 3622: 3623: 3624: 3625: 3626: 3627: 3628: 3629: 3630: 3631: 3632: 3633: 3634: 3635: 3736: 3737: 3738: 3739: 3840: 3841: 3842: 3843: 3844: 3845: 3846: 3947: 3948: 3949: 4050: 4151: 4152: 4153: 4154: 4255: 4356: 4357: 4458: 4459: 4360: 3961: 4062: 3963: 3864: 3765: 3666: 3667: 3768: 3769: 3770: 3771: 3672: 3673: 3574: 3575: 3676: 3577: 3678: 3679: 3580: 3681: 3782: 3783: 3784: 3885: 3886: 3887: 3888: 3789: 3890: 3891: 3792: 3793: 3794: 3795: 3796: 3797: 3798: 3799: 37length: 100_chartjs: {listeners: Array(1)}push: ƒ ()pop: ƒ ()shift: ƒ ()splice: ƒ ()unshift: ƒ ()__proto__: Array(0)
SensorChart.js:61 [_chartjs: {…}, push: ƒ, pop: ƒ, shift: ƒ, splice: ƒ, …]0: 24.31: 24.32: 24.33: 24.24: 24.15: 23.86: 22.87: 22.98: 23.59: 2410: 24.811: 24.812: 24.713: 24.514: 24.515: 24.516: 24.617: 24.518: 24.519: 24.520: 24.421: 24.422: 24.423: 24.424: 24.525: 24.426: 24.427: 24.428: 24.429: 24.430: 24.431: 24.432: 24.433: 24.434: 24.335: 24.436: 24.437: 24.538: 24.539: 24.540: 24.541: 24.442: 24.543: 24.544: 24.545: 24.546: 24.547: 24.448: 24.349: 24.450: 24.451: 24.452: 24.453: 24.554: 24.555: 24.556: 24.557: 24.558: 24.559: 24.560: 24.561: 24.562: 24.563: 24.564: 24.565: 24.566: 24.567: 24.468: 24.469: 24.470: 24.471: 24.472: 24.373: 24.374: 24.375: 24.376: 24.377: 24.378: 24.379: 24.380: 24.381: 24.482: 24.483: 24.384: 24.385: 24.386: 24.387: 24.388: 24.389: 24.490: 24.291: 24.392: 24.293: 24.294: 24.295: 24.296: 24.197: 24.198: 24.299: 24.1length: 100_chartjs: {listeners: Array(1)}push: ƒ ()pop: ƒ ()shift: ƒ ()splice: ƒ ()unshift: ƒ ()__proto__: Array(0)


Solution 1:[1]

For everyone who is still ending up here, this seems to be an actively tracked issue at the moment since about 2017 on their GitHub Repo (#90). Although the issue is closed at the moment (2021-Apr-01), it is obviously still a problem for a lot of users as it has received comments on GitHub itself quite recently as well as here on Stack Overflow.

Previously listed solutions:

Redraw:

Apparently including the redraw prop on the React-ChartJS-2 component call is supposed to force a redraw of the data:

return (
    <Line data={chartData} options={options} title="My Chart" ref={chartRef} redraw />
)

Sadly, this did nothing for me...

useEffect():

By tying the charts actual data into a useState() hook, it will trigger a component reload every time you change the data, which if you plan it right can also include initial data load.

const [chartData, setChartData] = useState(null);

// Data Fetch
useEffect(() => {
//...Async fetch my data from source and update state
});

// Attempt at triggering update whenever datasets change:
useEffect(() => {
    if (chartData !== null) {
      chartRef.current.chartInstance.update({
        preservation: true,
      });
    }
  }, [chartData]);

// Nested component to trigger rerender of only the graph for performance
const Graph = () => {
    return (
      <>
        {chartData ? (
          <Line data={chartData} options={options} title="My Chart" ref={chartRef} redraw />
        ) : null}
      </>
    );
  };

return (
    <Graph />
)

Sadly (again), this also did nothing...

Conclusion:

This appears to be a bug with how ChartJS was ported to React, meaning this appears to be an issue with the actual React-ChartJS-2 package.

TL;DR

Its a known issue on the React-ChartJS-2 GitHub (#90). Normal approaches do not work currently. Stay tuned there for updates.

Solution 2:[2]

After a few tinkering about I finally managed to get the Line graph to re-render when the data is received.

You may need to make use of both useState and useEffect, how I got around it is by updating the state to hold the datasets when data received has changed

const [data, setData] = React.useState<any>({ datasets: [{ data: [] }] });

And the useEffect with the data sets and labels as the dependencies

React.useEffect(() => {
    setData({
        labels: label,
        datasets: [
            {
                data: datavals,
                borderColor: "#59F5FF",
                backgroundColor: "none",
                pointBackgroundColor: "#59F5FF",
                pointBorderWidth: 5,
                pointHoverRadius: 10,
                tension: 0.4
            }
        ]
    });
}, [label, datavals]);

then further down in the Line component

return <Line data={data} />;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Graeme Ford
Solution 2 Dharman