WebSocket数据读取'fs'属性报错,React图表渲染问题求助
WebSocket数据可视化图表报错解决
问题描述
通过WebSocket连接Python程序与React的App.js,实现数据曲线可视化。面板1模块可正常显示数据,但尝试将WebSocket数据中的data["fs"]["s1"]["twist"]插入图表时,出现错误:App.js:51 Uncaught TypeError: Cannot read property 'fs' of null。
已尝试方案
- 在useEffect依赖数组中加入
[data],导致界面频繁卡顿,WebSocket连接多次断开 - 添加try-catch块,仍持续触发
fs属性读取错误 - 在socket的message事件监听中直接解析
event.data传入图表可正常工作,但打印state中的data显示为null
错误原因
- 初始state中
data为null,组件挂载时直接访问data["fs"]会触发空值报错 - useEffect内的图表更新逻辑写在socket监听外部,未等待数据更新就执行,此时
data仍为初始的null - 将
[data]加入依赖会导致useEffect重复执行,每次创建新WebSocket连接,引发卡顿与连接断开
解决方案
修复步骤
- 在socket的message事件回调中直接处理解析后的数据,同步更新图表,避免依赖state的异步更新延迟
- 使用可选链操作符
?.判断数据是否存在,确保访问深层属性前已有有效数据 - 保持WebSocket连接仅创建一次,组件卸载时关闭连接,避免重复连接
修改后的App.js代码
import React, { useState, useEffect } from 'react'; import Modal from './Modal/Modal' import {Chart as ChartJS,LinearScale,PointElement,LineElement,Tooltip,Legend} from 'chart.js'; import {Scatter } from 'react-chartjs-2'; ChartJS.register( LinearScale, PointElement, LineElement, Tooltip, Legend); export default function App() { const [data, setData] = useState(null); const [chartData,setChartData]=useState({ datasets: [ { label: 'A dataset', showLine:true, maintainAspectRatio:false, fill:false, data: [{x:3,y:1},{x:10,y:2},{x:5.5,y:3},{x:50,y:4},{x:5,y:5}], backgroundColor: 'rgba(255, 99, 132, 1)', borderColor: '#df9305' }] }); const [show,setShow] = useState(false); const updateChart = (twistValue) => { const newData = [ {x: twistValue, y: 1}, {x:2,y:2}, {x:5.5,y:3}, {x:5,y:4}, {x:5,y:5} ]; setChartData(prev => ({ ...prev, datasets: [{...prev.datasets[0], data: newData}] })); }; useEffect(() => { const socket = new WebSocket('ws://localhost:8000'); socket.addEventListener('message', (event) => { const parsedData = JSON.parse(event.data); setData(parsedData); // 直接用解析后的数据更新图表,无需等待state同步 if (parsedData?.fs?.s1?.twist !== undefined) { updateChart(parsedData.fs.s1.twist); } }); // 组件卸载时关闭WebSocket连接 return () => { socket.close(); }; }, []); return ( <div> <div className="home"> <div className="template-1" id="temp1"> <div className="panel-1"> <div className="panel-header"> <h1>Foresail</h1> <i className='bx bx-cog modal-trigger-panel'></i> </div> <div className="panel-body"> <div className="sec-5 modal-trigger-data" id="fs-sec-5" onClick={()=>setShow(true)}> {data?.fs?.s5?.twist ?? <span class="h1" id="h1-fs-s5">--</span>} <h2>TWIST</h2> <h3>s5</h3> </div> <div className="sec-4 modal-trigger-data" id="fs-sec-4" onClick={()=>setShow(true)}> {data?.fs?.s4?.twist ?? <span class="h1" id="h1-fs-s4">--</span>} <h2>TWIST</h2> <h3>s4</h3> </div> <div className="sec-3 modal-trigger-data" id="fs-sec-3" onClick={()=>setShow(true)}> {data?.fs?.s3?.twist ?? <span class="h1" id="h1-fs-s3">--</span>} <h2>TWIST</h2> <h3>s3</h3> </div> <div className="sec-2 modal-trigger-data" id="fs-sec-2" onClick={()=>setShow(true)}> {data?.fs?.s2?.twist ?? <span class="h1" id="h1-fs-s2">--</span>} <h2>TWIST</h2> <h3>s2</h3> </div> <div className="sec-1 modal-trigger-data" id="fs-sec-1" onClick={()=>setShow(true)}> {data?.fs?.s1?.twist ?? <span class="h1" id="h1-fs-s1">--</span>} <h2>TWIST</h2> <h3>s1</h3> </div> </div> </div> <div class="panel-3"> <div class="panel-header"> <h1>Courbes</h1> <i class='bx bx-cog modal-trigger-panel'></i> </div> <div class="panel-body"> <Scatter options={{showLines:true,legend:{display:false}}} data={chartData} /> </div> </div> </div> <Modal onClose={() => setShow(false)} show={show} /> </div> </div> ); }
Python代码无需修改
原Python的WebSocket服务逻辑正常,保持原样即可。
内容的提问来源于stack exchange,提问作者Feyto
相关产品推荐
相关产品推荐

