Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with websocket connection when trying to add dependencies

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={{display: "flex", flexDirection: "row"}}>
                            <div style={{width: "50%",height: "100%"}}>
                                <Scatter options={options5} data={chartDataPFS}/>
                            </div>
                            <div style={{width: "50%",height: "100%"}}>
                                <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,

like image 561
Feyto Avatar asked Oct 17 '25 15:10

Feyto


1 Answers

If you set the dependency to be selectedSection it should solve your problem. This is because that when you set the dependency to the functions it will rerender basically as fast as your computer allows, but if you set it to selectedSection it only rerender when that is updated and the correct value is included.

like image 137
LazyJ Avatar answered Oct 20 '25 05:10

LazyJ