DEV Community

Discussion on: Using WebSockets with React

Collapse
 
tzii profile image
Vu

I guess your code will create multiple instances of Websocket, you should put this in useEffect hook to avoid that

Collapse
 
muratcanyuksel profile image
Murat Can Yüksel

Hello, I have 4 components that I repeat the same method and it seems like each one waits its turn to display the data. I was wondering how to fix that, I guess you're taling about that? In my original code, I have useEffect in this manner :

 useEffect(() => {
    ws.onmessage = function (event) {
      const json = JSON.parse(event.data);
      try {
        if ((json.event = "data")) {
          dispatch(getOrderBookData(json.data));
        }
      } catch (err) {
        console.log(err);
      }
    };
    //clean up function
    return () => ws.close();
  }, []);
Enter fullscreen mode Exit fullscreen mode

What should I do to overcome the problem you mentioned?

Collapse
 
vsalvans profile image
Víctor Salvans Montesó

That's right. I will even go further and create a hook ( useWebsocket that uses useEffect internally) where you can pass the callback functions onopen and onmessage and returns a send function for instance or whatever you need from the hook.

Collapse
 
muratcanyuksel profile image
Murat Can Yüksel

Hey man, I wrote a reply to Vu's comment. Feel free to join the discussion :)

Thread Thread
 
tzii profile image
Vu • Edited

Every time the client receives new message => setBids called => component rerender => create new instance of Websocket => create new connection (1 request in devtools). This's not good, right :)))
This is my idea. You can check more in network tab in devtools and see the differents.


const apiCall = {
    event: 'bts:subscribe',
    data: { channel: 'order_book_btcusd' },
};
function App() {
    const [bids, setBids] = useState([0]);

    useEffect(() => {
        const ws = new WebSocket('wss://ws.bitstamp.net');
        ws.onopen = (event) => {
            ws.send(JSON.stringify(apiCall));
        };
        ws.onmessage = function (event) {
            const json = JSON.parse(event.data);
            try {
                if ((json.event == 'data')) {
                    setBids(json.data.bids.slice(0, 5));
                }
            } catch (err) {
                console.log(err);
            }
        };
        //clean up function
        return () => ws.close();
    }, []);
    const firstBids = bids.map((item, index) => (
        <div key={index}>
            <p> {item}</p>
        </div>
    ));

    return <div>{firstBids}</div>;
}
Enter fullscreen mode Exit fullscreen mode