I'm trying to implement WebSocket support into my app by following React Native's own tutorial at https://reactnative.dev/docs/network#websocket-support.
Here is my code:
function initializeSocket(socket:WebSocket){ socket.onopen = () => { store.dispatch(toggleWebsocketConnected(true)); }; socket.onclose = () => { store.dispatch(toggleWebsocketConnected(false)); }; socket.onerror = (e:any) => { console.log('websocket error', e); store.dispatch(toggleWebsocketConnected(false)); }; socket.onmessage = (e) => { processMessage(e); };}
In onerror
event handler (for now, ignore why error handler is called, this is not a "why can't I connect" question, but a TypeScript question) when it's triggered I'm getting a weird error at runtime:
TypeError [ERR_INVALID_THIS]: Value of "this" must be of type Event at new NodeError (/path/to/my/project/lib/internal/errors.js:371:5) at Event.[nodejs.util.inspect.custom] (/path/to/my/project/lib/internal/event_target.js:120:13) at formatValue (/path/to/my/project/lib/internal/util/inspect.js:763:19) at inspect (/path/to/my/project/lib/internal/util/inspect.js:340:10) at formatWithOptionsInternal (/path/to/my/project/lib/internal/util/inspect.js:2006:40) at formatWithOptions (/path/to/my/project/lib/internal/util/inspect.js:1888:10) at console.value (/path/to/my/project/lib/internal/console/constructor.js:323:14) at console.log (/path/to/my/project/lib/internal/console/constructor.js:359:61) at EventTarget.socket.onerror (/path/to/my/project/src/services/myproject/socket.ts:27:17) at EventTarget.dispatchEvent (/path/to/my/project/.vscode/.react/index.bundle:31193:27) {code: 'ERR_INVALID_THIS', stack: 'TypeError [ERR_INVALID_THIS]: Value of "this"…/myproject/.vscode/.react/index.bundle:31193:27)', message: 'Value of "this" must be of type Event', toString: ƒ, Symbol(kIsNodeError): true}
Vscode linter shows everything is fine though. When I hover over the onerror
function it shows:
(property) WebSocket.onerror: ((this: WebSocket, ev: Event) => any) | null
Two input arguments. So eventhough Vscode isn't complaining about my initial code, I also tried to change it to the following:
socket.onerror = (_:any, e:any) => { console.log('websocket error', e); store.dispatch(toggleWebsocketConnected(false)); };
Now, Vscode linter shows an error:
Type '(_: any, e: any) => void' is not assignable to type '(this: WebSocket, ev: Event) => any'.ts(2322)
If I run the code regardless of the error, I don't get a runtime error, yet _
is now an actual event object and e
is undefined:
What am I doing wrong? What is the correct form of doing it? I've stumbled upon a weird problem with this
keyword in arguments and TypeScript before (see Why are rest parameters undefined in TypeScript?) which indeed turned to be a Babel bug, which is now merged and fixed long ago.
How can I get it to work correectly?
UPDATE: I've managed to "work around" by turning the arrow function into a function with a function keyword:
socket.onerror = function(this:any, e:Event){ console.log('websocket error', e); store.dispatch(toggleWebsocketConnected(false)); };
It "works" now, though this is not an actual solution as I still can't use arrow functions, breaking my code style as I never use function keyword
functions in code (other than top-level simple definitions) anywhere in the app.
No it doesn't, it seemed to step correctly yet actually threw an error again when I reached a line to console.log
the event.