I am currently trying to add charts for the graphical part with React in an Electron software. Except that I added interactions with buttons (sections) to insert different data in the graphs depending on the click on one of the sections by the user (variable selectedSection). So I added in the dependencies of the useEffect() function the chartPMS and chartPFS functions to have access at the selectedSection variable.
The useEffect() function receives data continuously through a websocket from a python program. The problem is that when I run the code via the npm start
command, I get a data display with a very high frequency and this error continuously in the console : WebSocket connection to 'ws:<URL>/' failed: WebSocket is closed before the connection is established.
But the functions did receive changes to the selectedSection variable based on clicks on the different sections.
I should point out that I used the useEffect() function in this way before, it worked but I didn't have access to the updated version after clicking on one of the sections of the selectedSection variable:
useEffect(() => {
const socket = new WebSocket('ws://localhost:8000');
socket.addEventListener('message', (event) => {
setData(JSON.parse(event.data));
chartPFS(JSON.parse(event.data));
chartPMS(JSON.parse(event.data));
});
}, []);
I added selectedSection to the dependencies except that it refreshes both panels after clicking on one of the section buttons.
Here are the code:
App.js with 2 panels :
import React, { useState, useEffect, useRef, useSyncExternalStore } from 'react';
import Modal from './Modal/Modal'
import {Chart as ChartJS,LinearScale,PointElement,LineElement,Tooltip,Legend,Title,CategoryScale,elements} from 'chart.js';
import {Scatter, Line } from 'react-chartjs-2';
import { handleDataClick } from './Modal/Modal';
import { LineChart } from 'recharts';
import 'chart.js/auto';
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Tooltip,
Legend,
Title);
//--------------------------- OPTIONS GRAPHIQUE ----------------------------------//
export const options5 = {
elements: {
line: {
tension: 0.3,
},
},
responsive: true,
maintainAspectRatio:false,
plugins: {
showLine:true,
legend: false
},
};
//--------------------------- FUNCTION APP() ----------------------------------//
export default function App() {
let da;
const [data, setData] = useState(null);
const [show,setShow] = useState(false);
const [lastSelectedSection, setLastSelectedSection] = useState(null);
const h2f5Ref = useRef(null);
const h2f4Ref = useRef(null);
const h2f3Ref = useRef(null);
const h2f2Ref = useRef(null);
const h2f1Ref = useRef(null);
const h2m5Ref = useRef(null);
const h2m4Ref = useRef(null);
const h2m3Ref = useRef(null);
const h2m2Ref = useRef(null);
const h2m1Ref = useRef(null);
const [selectedDataType, setSelectedDataType] = useState({id:"fs-sec-1",selected:"twist"});
const [sectionData, setSectionData] = useState({
"fs-sec-1": { selectedDataType: 'twist' },
"fs-sec-2": { selectedDataType: 'twist' },
"fs-sec-3": { selectedDataType: 'twist' },
"fs-sec-4": { selectedDataType: 'twist' },
"fs-sec-5": { selectedDataType: 'twist' },
"ms-sec-1": { selectedDataType: 'twist' },
"ms-sec-2": { selectedDataType: 'twist' },
"ms-sec-3": { selectedDataType: 'twist' },
"ms-sec-4": { selectedDataType: 'twist' },
"ms-sec-5": { selectedDataType: 'twist' }
});
const [selectedSection, setSelectedSection] = useState("s1");
const [selectedSailP3,setSelectedSailP3]=useState("fs");
//----------------------- Graphiques Variables initiales -------------------//
const [chartDataPFS,setChartDataPFS]=useState({
datasets: [
{
label: 'Draft',
showLine:true,
data: [{x:3,y:1},{x:3.5,y:2},{x:5.5,y:3},{x:5.25,y:4},{x:5,y:5}],
backgroundColor: '#df9305',
borderColor: '#df9305'
}]
});
const [chartDataPMS,setChartDataPMS]=useState({
labels:["0","1","2","3","4"],
datasets: [
{
label: 'Draft',
showLine:true,
data: [0,2,3,2,0],
backgroundColor: '#df9305',
borderColor: '#df9305'
}]
});
//----------------------- Graphiques Fonctions mise à jour -------------------//
const chartPFS=(d) =>{
let dataToUse;
console.log(selectedSection)
dataToUse=[{x:0,y:0},
{x:3.3/2,y:d["fs"][selectedSection]["camber"]*0.75},
{x:3.3,y:d["fs"][selectedSection]["draft"]},
{x:(10-3.3)/2+3.3,y:d["fs"][selectedSection]["draft"]*0.55},
{x:10,y:0}];
setChartDataPFS({
datasets: [
{
label: 'Profile',
showLine:true,
maintainAspectRatio:false,
fill:false,
data: dataToUse,
backgroundColor: '#000000',
borderColor: '#000000'
}]
});
};
const chartPMS=(d) =>{
let dataToUse;
dataToUse=[0,
d["ms"][selectedSection]["camber"],
d["ms"][selectedSection]["draft"],
d["ms"][selectedSection]["draft"],
0];
setChartDataPMS({
labels:[0,1,2,3,4],
datasets: [
{
label: 'Profile',
maintainAspectRatio:false,
fill:false,
data: dataToUse,
borderColor: '#000000'
}]
});
};
//----------------------- Fonctions Récupération données au clic -------------------//
const handleClick = (id,h2Text) => {
const sectionId = id;
setSelectedDataType({id:sectionId,selected:h2Text});
};
const handleSectionClick=(section) =>{
setSelectedSection(section);
};
const handleSailP3Click=(sail) =>{
setSelectedSailP3(sail);
};
//----------------------- Mise à jour données -------------------//
useEffect(() => {
const socket = new WebSocket('ws://localhost:8000');
const handler = (event) => {
setData(JSON.parse(event.data));
chart1(JSON.parse(event.data));
chart2(JSON.parse(event.data));
chart3(JSON.parse(event.data));
chart4(JSON.parse(event.data));
chartPFS(JSON.parse(event.data));
chartPMS(JSON.parse(event.data));
};
socket.addEventListener('message', handler);
return () => {
socket.removeEventListener('message', handler);
socket.close();
};
}, [selectedSection]);
return (
<div>
<div className="home">
<div className="template-1" id="temp1">
<div className="panel-1">
<div className="panel-header">
<h1>FORESAIL data</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={()=>{handleClick("fs-sec-5",h2f5Ref.current.textContent);setShow(true);}} >
{data && sectionData["fs-sec-5"].selectedDataType ? <span class="h1" id="h1-fs-s5">{data["fs"]["s5"][sectionData["fs-sec-5"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s5">--</span>}
<h2 ref={h2f5Ref}>{sectionData["fs-sec-5"].selectedDataType ? sectionData["fs-sec-5"].selectedDataType.toUpperCase() : "TWIST"}</h2>
<h3>s5</h3>
</div>
<div className="sec-4 modal-trigger-data" id="fs-sec-4" onClick={()=>{handleClick("fs-sec-4",h2f4Ref.current.textContent);setShow(true);}}>
{data && sectionData["fs-sec-4"].selectedDataType ? <span class="h1" id="h1-fs-s4">{data["fs"]["s4"][sectionData["fs-sec-4"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s4">--</span>}
<h2 ref={h2f4Ref}>{sectionData["fs-sec-4"].selectedDataType ? sectionData["fs-sec-4"].selectedDataType.toUpperCase() : "TWIST"}</h2>
<h3>s4</h3>
</div>
<div className="sec-3 modal-trigger-data" id="fs-sec-3" onClick={()=>{handleClick("fs-sec-3",h2f3Ref.current.textContent);setShow(true);}}>
{data && sectionData["fs-sec-3"].selectedDataType ? <span class="h1" id="h1-fs-s3">{data["fs"]["s3"][sectionData["fs-sec-3"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s3">--</span>}
<h2 ref={h2f3Ref}>{sectionData["fs-sec-3"].selectedDataType ? sectionData["fs-sec-3"].selectedDataType.toUpperCase() : "TWIST"}</h2>
<h3>s3</h3>
</div>
<div className="sec-2 modal-trigger-data" id="fs-sec-2" onClick={()=>{handleClick("fs-sec-2",h2f2Ref.current.textContent);setShow(true);}}>
{data && sectionData["fs-sec-2"].selectedDataType ? <span class="h1" id="h1-fs-s2">{data["fs"]["s2"][sectionData["fs-sec-2"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s2">--</span>}
<h2 ref={h2f2Ref}>{sectionData["fs-sec-2"].selectedDataType ? sectionData["fs-sec-2"].selectedDataType.toUpperCase() : "TWIST"}</h2>
<h3>s2</h3>
</div>
<div className="sec-1 modal-trigger-data" id="fs-sec-1" onClick={()=>{handleClick("fs-sec-1",h2f1Ref.current.textContent);setShow(true);}}>
{data && sectionData["fs-sec-1"].selectedDataType ? <span class="h1" id="h1-fs-s1">{data["fs"]["s1"][sectionData["fs-sec-1"].selectedDataType]}</span> : <span class="h1" id="h1-fs-s1">--</span>}
<h2 ref={h2f1Ref}>{sectionData["fs-sec-1"].selectedDataType ? sectionData["fs-sec-1"].selectedDataType.toUpperCase() : "TWIST"}</h2>
<h3>s1</h3>
</div>
</div>
</div>
<div class="panel-5">
<div class="panel-header">
<h1>SAILS sections</h1>
<i class='bx bx-cog modal-trigger-panel'></i>
</div>
<div class="panel-body">
<div class="profil-container" style=>
<div style=>
<Scatter options={options5} data={chartDataPFS}/>
</div>
<div style=>
<Line options={options5} data={chartDataPMS}/>
</div>
</div>
<div class="button-sec">
<input type="submit" value="Section 5" class={`section5 ${selectedSection === "s5" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s5")}}/>
<input type="submit" value="Section 4" class={`section4 ${selectedSection === "s4" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s4")}}/>
<input type="submit" value="Section 3" class={`section3 ${selectedSection === "s3" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s3")}}/>
<input type="submit" value="Section 2" class={`section2 ${selectedSection === "s2" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s2")}}/>
<input type="submit" value="Section 1" class={`section1 ${selectedSection === "s1" ? 'active' : ''}`} onClick={()=>{handleSectionClick("s1")}}/>
</div>
<div class="button-sail">
<input type="submit" value="Foresail" class="btn-hs modal-trigger-hs"/>
<input type="submit" value="Mainsail" class="btn-ms modal-trigger-ms"/>
</div>
</div>
</div>
</div>
<Modal onClose={() => setShow(false)} show={show} Data={selectedDataType} sectionData={sectionData} setSectionData={setSectionData}/>
</div>
</div>
);
}
Python :
import asyncio
import random
import datetime
import websockets
import json
sv={"fs":{
"s5":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s4":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s3":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s2":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s1":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
},
"ms":{
"s5":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s4":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s3":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s2":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
"s1":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"saglat":10,"saglong":10},
}}
async def handler(websocket, path):
while True:
#log_decoder()
for key1 in sv:
for key2 in sv[key1]:
sv[key1][key2]["entry"] = random.randint(1, 10)
sv[key1][key2]["cfwd"] = random.randint(1, 10)
sv[key1][key2]["camber"] = random.randint(1, 10)
sv[key1][key2]["draft"] = random.randint(1, 4)
sv[key1][key2]["caft"] = random.randint(1, 10)
sv[key1][key2]["exit"] = random.randint(1, 10)
sv[key1][key2]["twist"] = random.randint(1, 10)
sv[key1][key2]["saglat"] = random.randint(1, 10)
sv[key1][key2]["saglong"] = random.randint(1, 10)
#data = [random.randint(0, 20) for _ in range(10)]
await websocket.send(json.dumps(sv))
await asyncio.sleep(1)
start_server = websockets.serve(handler, "localhost", 8000)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Regards,
from
Error with websocket connection when trying to add dependencies