简体   繁体   中英

React Chart Js Class Component

I converted my code to a class component and things started to break. I figured out where it's breaking but I can't seem to figure out why its breaking. Think you guys can help me out?

What happens is when I change the name in this input field (red arrow section) componentDidMount fires off and gives me this error.

So I've narrowed down the issue to when I setState and do data: chartData in componentDidMount. If that bit of code is commented out, it works otherwise it doesn't.

Chartjs can take an empty object hence why I'm doing the check to only update the value if there is something to update it with. But yeah, I really don't know what's wrong or how to fix it...

All my code was working before I made it into a class component, I would change it back but that input field at the top, I was having trouble dynamically updating it before. I will show my before and after code too. BTW I did remove some functions as to not make the code so lengthy and I can verify those functions were not breaking my code

Chart View在此处输入图片说明

在此处输入图片说明

Before Change

import React, {useEffect, useState} from 'react'
import {Redirect} from "react-router-dom";
import {connect} from 'react-redux'
import {Line} from "react-chartjs-2";
import moment from "moment";
import "./DeviceDetails.css"
import axios from "axios";

const DeviceDetails = (props) => {
    const {auth, device, sensorData,deviceName} = props
    const [chartData, setChartData] = useState({})
    const today = moment().format().split("T")[0]
    const localTime = moment(device.dateTime).format("DD/MM/YYYY HH:mm").toString()

    
    useEffect(() => {
        let chartData = {}

        if (sensorData) {
            chartData = sensorData.map(data => {
                const container = {};
                container.x = moment(data.dateTime)
                container.y = data.soilMoisturePercent
                return container
            })
        }


        const chart = () => {
            setChartData({
                labels: [moment().startOf('day'), moment().endOf('day')],
                datasets: [
                    {
                        label: "Moisture Levels",
                        data: chartData,
                        backgroundColor: ['rgba(75,192,192,0.6)'],
                        borderWidth: 4
                    }
                ],
            })
        }

        chart()
    }, [sensorData]);

    const options = {...}

    if (!auth.uid) {
        return <Redirect to="/signin"/>
    } else {
        return (
            <div className="fitting dashboard-container section">
                <div className="device-details z-depth-0">
                    <div className="card-content">
                        <p className="card-title"> Name - {deviceName} </p>
                        <p> Date/Time - {localTime} </p>
                        <p> Battery Percent - {device.battery} </p>
                        <p> Moisture Percent - {device.soilMoisturePercent} </p>
                    </div>
                    <div className="card-action grey lighten-4 grey-text">
                        <input type="date" defaultValue={today} max={today} onChange={(event => handleChange(event.target.value))}/>
                        <Line data={chartData} options={options}/>
                    </div>
                </div>
            </div>
        )
    }
}

const mapStateToProps = (state, ownProps) => {
    const id = ownProps.match.params.id;
    const devices = state.device.devices;
    const sensors = state.device.sensorData;
    const device = devices ? devices[id] : null
    const deviceName = state.auth.user.devices[id].Value
    const sensorData = sensors ? sensors[id] : null
    return {
        auth: state.firebase.auth,
        device: device,
        sensorData: sensorData,
        deviceName: deviceName,
    }
}

export default connect(mapStateToProps)(DeviceDetails)

After Change to Class Component

import React, {Component} from 'react'
import {Redirect} from "react-router-dom";
import {connect} from 'react-redux'
import {Line} from "react-chartjs-2";
import moment from "moment";
import "./DeviceDetails.css"
import axios from "axios";
import {updateDeviceName} from "../../store/Actions/AuthActions";

class DeviceDetails extends Component {
    constructor(props) {
        super(props);
        this.state = {
            chartData: {},
            options: {...},
            devName: this.props.deviceName,
            deviceId: this.props.device.deviceId
        }
    }

    componentDidMount = () => {
        const {sensorData} = this.props

        let chartData = {}

        if (sensorData) {
            chartData = sensorData.map(data => {
                const container = {};
                container.x = moment(data.dateTime)
                container.y = data.soilMoisturePercent
                return container
            })
        }

        this.setState({
            chartData: {
                labels: [moment().startOf('day'), moment().endOf('day')],
                datasets: [
                    {
                        label: "Moisture Levels",
                        data: chartData,
                        backgroundColor: ['rgba(75,192,192,0.6)'],
                        borderWidth: 4
                    }
                ],
            }
        })
    }

    handleNameChange = (event) => {
        this.setState({
            devName: event.target.value
        })
    }

    updateDeviceName = () => {
        this.props.updateDeviceName(this.state)
    }

    render() {
        const {auth, device} = this.props
        const today = moment().format().split("T")[0]
        const localTime = moment(device.dateTime).format("DD/MM/YYYY HH:mm").toString()

        if (!auth.uid) {
            return <Redirect to="/signin"/>
        } else {
            return (
                <form>
                    <div className="fitting dashboard-container section">
                        <div className="device-details z-depth-0">
                            <div className="card-content">
                                <input type="text" id="devName" value={this.state.devName}
                                       onChange={this.handleNameChange} onBlur={this.updateDeviceName}/>
                                <p> Date/Time - {localTime} </p>
                                <p> Battery Percent - {device.battery} </p>
                                <p> Moisture Percent - {device.soilMoisturePercent} </p>
                            </div>
                            <div className="card-action grey lighten-4 grey-text">
                                <input type="date" defaultValue={today} max={today}
                                       onChange={(event => this.handleChange(event.target.value))}/>
                                <Line data={this.state.chartData} options={this.state.options}/>
                            </div>
                        </div>
                    </div>
                </form>
            )
        }
    }
}

const mapStateToProps = (state, ownProps) => {
    const id = ownProps.match.params.id;
    const devices = state.device.devices;
    const sensors = state.device.sensorData;
    const device = devices ? devices[id] : null
    const deviceName = state.auth.user.devices[id].Value.toString()
    const sensorData = sensors ? sensors[id] : null
    return {
        auth: state.firebase.auth,
        device: device,
        sensorData: sensorData,
        deviceName: deviceName,
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        updateDeviceName: (device) => dispatch(updateDeviceName(device))
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(DeviceDetails)

Well..... I found the answer... The errors are different but it fixed everything

react-chartjs state update error

Adding redraw prop to my fixed all the issues...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM