question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot JSON.parse received data when using socket.io

See original GitHub issue

When using socket.io, I am emitting a message from the server:

io.emit('test', 'hello, world!')

but on the client (in the received MessageEvent), it results in:

data: "42["test","hello, world!"]"

or, in case of using an actual JSON payload:

io.emit('test', { message: 'hello, world!' })

on the client:

data: "42["test",{"message":"hello, world!"}]"

(Also, in case of using send instead of emit, the result is the same.)

which are both none-parseable as a JSON object. Is this expected or is this a a user error? My test setup is very minimal with the following config:

const Test = () => {
    const options = useMemo(
        () => ({
            share: true,
            fromSocketIO: true,
            onMessage: (_event: MessageEvent) => {},
            onClose: (_event: MessageEvent) => {},
            onOpen: (_event: MessageEvent) => {},
            onError: console.error,
        }),
        [],
    )

    const [sendMessage, lastMessage, readyState] = useWebSocket(
        'ws://localhost:3000',
        options,
    )

    console.log(lastMessage)

    return (
        <div />
    )
}

Thanks in advance, AS

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
robtaussigcommented, Jun 20, 2019

I like it. If you are interested, this can potentially be a useful add-on that a developer can import into their component instead of the core hook, so they don’t have to think about socketIO parsing.

1reaction
GGAlanSmitheecommented, Jun 20, 2019

@robtaussig thanks for the explanation and additional work. What you say makes sense, and I actually ended up doing something in the lines of what you do:

I created an abstraction hook over the on you provide out of the box, where I handle message parsing, updates, memoization etc.

import { useMemo } from 'react'
import useWebSocket from 'react-use-websocket'

interface ISocketIOEvent {
    type: string
    payload: any
}

const emptyEvent: ISocketIOEvent = {
    type: 'empty',
    payload: null,
}

const getSocketData = (event: MessageEvent) => {
    if (!event || !event.data) {
        return emptyEvent
    }

    const match = event.data.match(/\[.*]/)

    if (!match) {
        return emptyEvent
    }

    const data = JSON.parse(match)

    if (!Array.isArray(data) || !data[1]) {
        return emptyEvent
    }

    return {
        type: data[0],
        payload: data[1],
    }
}

const useSocketIO = (): ISocketIOEvent => {
    const options = useMemo(
        () => ({
            share: true,
            fromSocketIO: true,
            onMessage: (_event: MessageEvent) => {},
            onClose: (_event: MessageEvent) => {},
            onOpen: (_event: MessageEvent) => {},
            onError: console.error,
        }),
        [],
    )

    const [, lastMessage] = useWebSocket(
        'ws://localhost:3000', // todo - use secure wss
        options,
    )

    return useMemo(() => getSocketData(lastMessage), [lastMessage])
}

export { ISocketIOEvent, useSocketIO }

(since I’m only interested in the last data for the time being, I don’t return sendMessage or readyState, but that could be added ofcourse.)

Read more comments on GitHub >

github_iconTop Results From Across the Web

node.js - SocketIO cannot access JSON properties from ON
var data = {username: "test"}; socket.emit('request_username', data);. Then, on the receiving side, you would have: socket.
Read more >
Server API - Socket.IO
Defaults to an instance of the Adapter that ships with socket.io which is memory based. See socket.io-adapter. If no arguments are supplied ...
Read more >
WebSockets and Node.js - testing WS and SockJS by building ...
Whenever our server receives a message, we use JSON.parse to get the message contents, and load our client metadata for this socket from...
Read more >
Can not get parameter from req.body with POST request in ...
var express = require('express'); · var bodyParser = require('body-parser') · var router = express.Router(); · var jsonParser = bodyParser.json(); ...
Read more >
Writing WebSocket client applications - Web APIs | MDN
The constructor will throw a SecurityError if the destination doesn't allow access. This may happen if you attempt to use an insecure connection ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found