0

So I'm having issues with a single component that displays a list pulled from a resource server. Then it uses Stompjs to establish a websocket and send messages. When I load the client, the Dev Console shows logs that it tries to call onConnected method() twice as my logs show two newUser messages sent from a single load of the component.

When I try to call the submitBid() method it throws a type error saying that

"TypeError: Cannot read properties of undefined (reading 'send') at submitBid (AuctionList.js:76:1)"

Which I'm not sure why it would be undefined on that line when it's defined and running fine in the function on line 36 which runs before the method that fails. I've been stuck on this for several days so hopefully someone can tell me what I've got wrong in the code... Here is the component code....

import React from 'react'
import Stomp from 'stompjs';
import SockJS from 'sockjs-client';
import {useState, useEffect } from 'react';

function AuctionList({user, authCredentials, token}) {

 
 const [auctionItems, setAuctionItems] = useState([]);

 const [userData, setUserData] = useState({
                                            email: user.email,
                                            name: user.name,
                                            message: ''
                                          });

  const [bid, setBid] = useState(0.00);

  let stompClient;
  let socket;



const connect = async () => {
      socket = new SockJS('http://localhost:8080/ws')
      stompClient = Stomp.over(socket)
      stompClient.connect({}, onConnected, onError)
}



const onConnected = async () => {

  stompClient.subscribe('/topic/bids', onMessageReceived)

  stompClient.send("/app/socket.newUser",
      {},
      JSON.stringify({
          sender: user.name,
          type: 'NEW_USER',
          time: Date.now()
      })
  )
}



 
const onError = async (err) => {
  console.log(err);
 
}


const handleChange = async (e) =>{ 
  setBid(e.target.value);
}


const submitBid =  async (item) => { 
  

  let newMessage = {
                type: "BID",
                newBid: {
                        itemId: item.id,
                        email: user.email,
                        bidPrice: bid,
                        bidTime: new Date().getTime()
                       },
                sender: userData.email,
                time: new Date().getTime()
      };

            try { 
              stompClient.send("/socket.send", {}, JSON.stringify(newMessage));
            } catch(err){ 
              console.log(err); }
}


const onMessageReceived = async (payload)=>{
  console.log("onMessageReceived")
  console.log(payload)
}



const getAuctionList = async () => {

    const url = "http://localhost:8080/auctionlist";
  
    const init = {
      method: "GET",
        headers: {
            'Content-type': 'application/json',
            'Authorization': `Bearer ${token}`, // notice the Bearer before your token
        },
    };

    fetch(url, init)
    .then(response => response.json())
    .then(response => {setAuctionItems(response)})
};


useEffect( () => {
  getAuctionList();
  connect();
}, []);


return (
    <ul>  
        {auctionItems.map( item =>  {
          return(                <div key={item.id} className = "auctionItemComponent">
                <h3>{item.name}</h3>
                <span>{item.desc}</span>
                <span>Current Bid: ${item.itemStartingPrice}</span>
                <span>Minimum Bid: {item.itemMinBid}</span>
                <span>Time left</span>
        
                <input type="number" id="bidInput_" name="bidInput" onChange={handleChange} ></input>
                <button type='submit' onClick={submitBid}>Submit bid</button>
              </div>)

        })}
    </ul> 
  )
}



export default AuctionList

Also I realize I have a bunch of async functions that don't have any awaits. I tried adding those in, but it was no change.

1 Answers1

0

The issue here is not with stompjs but with the scoping. You have stompClient inside React Component but the one from submitBid is different. You can do it in different ways.

  1. Put stompjs in global stage as in example here: https://playcode.io/972045

  2. You can use useRef to have the client inside the React Component and have React do the tracking of any modifications.

I personally think something like a "connection" should stay away from inside a React Component. You should have the connection configs in a different file and import an instance to the JSX file.

Sujil Maharjan
  • 1,307
  • 10
  • 12