How to retrieve data from JSON using reactJS and placing them in the right place?

Question:

I would like to retrieve the data from a JSON that is sent by a python program and place it in the corresponding boxes via the dictionary keys. I have tried to retrieve the data like this but it does not display the corresponding values to the dictionary keys. So I would like to know how to solve this problem?

I also don’t know how I could make sure that I take the corresponding data according to the h2 texts and ids of each section?

Here are the code:

App.js :

import React, { useState, useEffect } from 'react';
import Modal from './Modal/Modal'
//JSON.parse(event.data)

export default function App() {
  const [data, setData] = useState(null);
  const [show,setShow] = useState(false);

  useEffect(() => {
    const socket = new WebSocket('ws://localhost:8000');

    socket.addEventListener('message', (event) => {
      setData(event.data);
    });
  }, []);

  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="hs-sec-5" onClick={()=>setShow(true)}>
                        {data ? <span class="h1" id="h1-fs-s5">{data.fs.s5.entry}</span> : <span class="h1" id="h1-fs-s5">--</span>}
                        <h2>TWIST</h2>
                        <h3>s5</h3>
                    </div>
                    <div className="sec-4 modal-trigger-data" id="hs-sec-4" onClick={()=>setShow(true)}>
                        {data ? <span class="h1" id="h1-fs-s4">{data[1]}</span> : <span class="h1" id="h1-fs-s4">--</span>}
                        <h2>TWIST</h2>
                        <h3>s4</h3>
                    </div>
                    <div className="sec-3 modal-trigger-data" id="hs-sec-3" onClick={()=>setShow(true)}>
                        {data ? <span class="h1" id="h1-fs-s3">{data[2]}</span> : <span class="h1" id="h1-fs-s3">--</span>}
                        <h2>TWIST</h2>
                        <h3>s3</h3>
                    </div>
                    <div className="sec-2 modal-trigger-data" id="hs-sec-2" onClick={()=>setShow(true)}>
                        {data ? <span class="h1" id="h1-fs-s2">{data[3]}</span> : <span class="h1" id="h1-fs-s2">--</span>}
                        <h2>TWIST</h2>
                        <h3>s2</h3>
                    </div>
                    <div className="sec-1 modal-trigger-data" id="hs-sec-1" onClick={()=>setShow(true)}>
                        {data ? <span class="h1" id="h1-fs-s1">{data[4]}</span> : <span class="h1" id="h1-fs-s1">--</span>}
                        <h2>TWIST</h2>
                        <h3>s1</h3>
                    </div>
                    </div>
                </div>
                </div>
                <Modal onClose={() => setShow(false)} show={show} />
            </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,"sag_lat":10,"sag_long":10},
    "s4":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    "s3":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    "s2":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    "s1":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    },
    "ms":{
    "s5":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    "s4":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    "s3":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    "s2":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},
    "s1":{"entry":2,"cfwd":3,"camber":2,"draft":3,"caft":5,"exit":5,"twist":15,"sag_lat":10,"sag_long":10},    
    }}
async def handler(websocket, path):
    while True:
        #log_decoder()
        
        #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,

Asked By: Feyto

||

Answers:

I’m not very well versed in Python libraries, so I’ll just address the front-end JavaScript, which is where the problem seems to be.

Based on what I read in the Python Docs for
websockets
and
json, it seems that the WebSockets server is sending a JSON format string of sv.
So the problem is likely the front-end indexing a string with data[1] being: ", and trying to access an undefined property of the string with data.fs.s5.entry to get an error like:
ReferenceError: reference to undefined property "x"
(More on property accessors).

So parsing the JSON string to a JavaScript object should solve the problem for getting data, and then just get the properties of data in the JSX:

import React, { useState, useEffect } from "react"
import Modal from "./Modal/Modal"

export default function App() {
  const [data, setData] = useState(null)
  const [show, setShow] = useState(false)

  useEffect(() => {
    const socket = new WebSocket("ws://localhost:8000")

    socket.addEventListener("message", event => {
      setData(JSON.parse(event.data))
    })
  }, [])

  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">
              {data
                ? /* array of JSX elements */
                  Object.entries(data.fs).map(([s1Tos5, properties]) => (
                    <div
                      className={`sec-${s1Tos5.replace("s", "")} modal-trigger-data`}
                      id={`hs-sec-${s1Tos5.replace("s", "")}`}
                      onClick={() => setShow(true)}
                    >
                      <span class="h1" id={`h1-fs-${s1Tos5}`}>
                        {properties.entry}
                      </span>
                      <h2>{properties.twist}</h2>
                      <h3>{s1Tos5}</h3>
                    </div>
                  ))
                : /* add a placeholder element for when data is loading */
                  Array(5).map((_value, index) => (
                    <div
                      className={`sec-${index + 1} modal-trigger-data`}
                      id={`hs-sec-s${index + 1}`}
                      onClick={() => setShow(true)}
                    >
                      <span class="h1" id={`h1-fs-s${index + 1}`}>
                        ---
                      </span>
                      <h2>TWIST</h2>
                      <h3>s{index + 1}</h3>
                    </div>
                  ))}
            </div>
          </div>
        </div>
        <Modal onClose={() => setShow(false)} show={show} />
      </div>
    </div>
  )
}

Hope this helps!

Answered By: Nyctfall