Я преобразовал свой код в компонент класса, и все начало ломаться. Я понял, где он ломается, но я не могу понять, почему он ломается. Думаете, вы, ребята, можете мне помочь?
Что происходит, так это то, что когда я меняю имя в этом поле ввода (раздел с красной стрелкой), компонентDidMount срабатывает и дает мне эту ошибку.
Поэтому я сузил проблему до того, когда я setState и делаю данные: chartData в componentDidMount. Если этот фрагмент кода закомментирован, он работает, иначе нет.
Chartjs может принимать пустой объект, поэтому я выполняю проверку только для обновления значения, если есть что-то, что можно обновить. Но да, я действительно не знаю, что не так и как это исправить...
Весь мой код работал до того, как я превратил его в компонент класса, я бы изменил его обратно, но это поле ввода вверху, у меня были проблемы с его динамическим обновлением раньше. Я также покажу свой код до и после. Кстати, я удалил некоторые функции, чтобы не делать код таким длинным, и я могу убедиться, что эти функции не нарушают мой код.
До изменения
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)
После изменения компонента класса
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)