未处理的拒绝 (TypeError):无法读取 null 的 属性 'getContext'

Unhandled Rejection (TypeError): Cannot read property 'getContext' of null

在我的应用程序中有 3 个页面,分别是登录、注册和仪表板。当我在登录时重定向回仪表板时出现此错误。 错误出现在称为传感器读数图表的组件中 SensorReadingChart.js

class SensorReadingChart extends Component {

    _isMounted = false;
    chartRef = React.createRef();
    constructor(props) {
        super(props);
        threshold = props.threshold
        xAxisLabel = props.xAxisLabel
        yAxisLabel = props.yAxisLabel
        chartTitle = props.chartTitle
        x = props.x
        y = props.y
        location = props.location
        icon = props.icon
        apiEndPoint = props.apiEndPoint
        yUnit = props.yUnit
        themeColor = props.themeColor

        this.state = {
            sensorReadings:[]
        }
    }

    render() {
        dataPoints = this.state.sensorReadings.map(
            (sensor) => {
                return {
                    x: sensor[x], //change this to proper key
                    y: sensor[y], //change this to proper key
                    location: sensor[location], //change this to proper key
                }
            });
        thresholdLine = this.state.sensorReadings.map(
            (sensor) => {
                return {
                    x: sensor.id, //change this to proper key
                    y: threshold,
                }
            });
        options = {
            type: "line",
            data: {
                xLabels: dataPoints.map(x=>{return x.x}),
                datasets: [
                    {
                        data: dataPoints.map(y=>{return y.y}), //Sample data set [{x:1, y:21},{x:2, y:25},{x:3, y:31},{x:4, y:11},]
                        showLine: true,
                        fill: false,
                        borderColor: themeColor[1],
                        label: yAxisLabel+" Graph",
                        pointBackgroundColor: function(context) {
                            let index = context.dataIndex;
                            let value = context.dataset.data[index];
                            return value > threshold ? themeColor[0] : 'transparent';
                        },
                        pointBorderColor: function(context) {
                            let index = context.dataIndex;
                            let value = context.dataset.data[index];
                            return value > threshold ? themeColor[0] : 'transparent';
                        }
                    },
                    {
                        data: thresholdLine.map(y=>{return y.y}),
                        showLine: true,
                        borderColor: themeColor[0],
                        fill: false,
                        pointBorderColor: "transparent",
                        label: "threshold = "+threshold+" "+yUnit
                    }
                ]
            },
            options: {
                animation: {
                    duration: 0
                },
                tooltips: {
                    callbacks: {
                        label: function(tooltipItem, data) {
                            let label = yAxisLabel+" : "+tooltipItem.yLabel+" F  |  "+xAxisLabel+" : "+tooltipItem.xLabel;


                            if (tooltipItem.yLabel > threshold) {
                                label += "  |  Location : "+data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].location //change this to proper key

                            }
                            return label;
                        }
                    }
                },
                scales: {
                    yAxes: [
                        {
                            scaleLabel: {
                                display: true,
                                labelString: yAxisLabel + " in " + yUnit,
                            },
                        },
                    ],
                    xAxes: [
                        {
                            scaleLabel: {
                                display: true,
                                labelString: xAxisLabel,
                            },
                        },
                    ],
                },
            }
        }

        if(this.state.sensorReadings.length === 0)
        {
            return (<h5 className="card-subtitle mb-2 text-muted " align={"center"}><i className="bi bi-lightning"/>No Readings Yet!</h5>)
        }
        else{
        return (

            <div>
                <div><big><i className={icon} style={{color: themeColor[0]}}/>{chartTitle}</big></div>
                <br/>
                <canvas
                    id="myChart"
                    ref={this.chartRef}
                />
            </div>
        )}
    }
    componentDidMount() {
        this._isMounted = true;
        if(this._isMounted){
        SensorService.getSensorReadings(apiEndPoint).then((response)=>{
            const sensorReadings = response.data
            this.setState({sensorReadings})
            const myChartRef = this.chartRef.current.getContext("2d");
            new Chart(myChartRef, options);
        });
    }
    }

    componentWillUnmount(){
        this._isMounted = false;
    }
    

}

export default SensorReadingChart;

所以我想在没有这个错误的情况下重新登录页面 这是完整的错误

Unhandled Rejection (TypeError): Cannot read property 'getContext' of null (anonymous function) src/components/SensorReadingChart.js:154

152 |         const sensorReadings = response.data
153 |         this.setState({sensorReadings})
> 154 |         const myChartRef = this.chartRef.current.getContext("2d");
    | ^  155 |         new Chart(myChartRef, options);
156 |     });
157 | }

查看已编译 此屏幕仅在开发中可见。如果应用程序在生产中崩溃,它不会出现。 打开浏览器的开发人员控制台以进一步检查此错误。单击 'X' 或按 ESC 关闭此消息。

chartRef = React.createRef();

这个

this.chartRef = React.createRef();

添加

...
class SensorReadingChart extends Component {

    _isMounted = false;
    chartRef = React.createRef(); // <-- HERE!!
    constructor(props) {
        super(props);
...

基本上,JavaScript 不能像上面那样直接在 class 下有变量,这出乎意料。所以上面的行移动:

...
class SensorReadingChart extends Component {

    constructor(props) {
        super(props);
        this._isMounted = false;  // <-- WITH IT!!
        this.chartRef = React.createRef(); // <-- HERE!!
...

this问题好麻烦


为了避免this问题,我强烈推荐功能组件风格,如果你有特殊情况。在功能组件样式中,this 的实例总是清晰的。